From 5c31efd429e361947b7c54252145261a141c284e Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Tue, 12 Nov 2019 16:02:02 -0800 Subject: [PATCH 001/243] Typo in literal_representation.rs Octal numbers can't have 8 in them ;) --- clippy_lints/src/literal_representation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 8ddd54bb7a38..6681b8e6b98f 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -35,7 +35,7 @@ declare_clippy_lint! { /// **Known problems:** /// - Recommends a signed suffix, even though the number might be too big and an unsigned /// suffix is required - /// - Does not match on `_128` since that is a valid grouping for decimal and octal numbers + /// - Does not match on `_128` since that is a valid grouping for decimal and hexadecimal numbers /// /// **Example:** /// From b13f4e4fafa59402be86f377e360cba215818f8a Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Mon, 25 Nov 2019 16:28:46 -0800 Subject: [PATCH 002/243] Update literal_representation.rs --- clippy_lints/src/literal_representation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 6681b8e6b98f..2d50d64fc65f 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -35,7 +35,7 @@ declare_clippy_lint! { /// **Known problems:** /// - Recommends a signed suffix, even though the number might be too big and an unsigned /// suffix is required - /// - Does not match on `_128` since that is a valid grouping for decimal and hexadecimal numbers + /// - Does not match on `_128` since that is a valid grouping for decimal numbers /// /// **Example:** /// From aef266289680ba39b41fd1e3333b572c84bc67aa Mon Sep 17 00:00:00 2001 From: Ian Kronquist Date: Mon, 25 Nov 2019 16:30:46 -0800 Subject: [PATCH 003/243] Update literal_representation.rs --- clippy_lints/src/literal_representation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 2d50d64fc65f..eba6a4fdbb9d 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -35,7 +35,7 @@ declare_clippy_lint! { /// **Known problems:** /// - Recommends a signed suffix, even though the number might be too big and an unsigned /// suffix is required - /// - Does not match on `_128` since that is a valid grouping for decimal numbers + /// - Does not match on `_127` since that is a valid grouping for decimal and octal numbers /// /// **Example:** /// From 4cc5b098aed8dab8a5094b1e819eb99f1217ed43 Mon Sep 17 00:00:00 2001 From: mgr-inz-rafal Date: Mon, 3 Feb 2020 21:19:50 +0100 Subject: [PATCH 004/243] Initial lint infrastructure --- clippy_lints/src/needless_bool.rs | 11 ++++++++++- tests/ui/bool_comparison.fixed | 7 +++++++ tests/ui/bool_comparison.rs | 7 +++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index db4012146dff..2814f0de7cfc 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -193,9 +193,18 @@ fn check_comparison<'a, 'tcx>( ) { use self::Expression::*; - if let ExprKind::Binary(_, ref left_side, ref right_side) = e.kind { + if let ExprKind::Binary(op, ref left_side, ref right_side) = e.kind { let (l_ty, r_ty) = (cx.tables.expr_ty(left_side), cx.tables.expr_ty(right_side)); if l_ty.is_bool() && r_ty.is_bool() { + if let BinOpKind::Eq = op.node { + if let ExprKind::Unary(unop, exx) = right_side.kind + { + if let UnOp::UnNot = unop { + // TODO: Lint here + } + } + } + let mut applicability = Applicability::MachineApplicable; match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { (Bool(true), Other) => left_true.map_or((), |(h, m)| { diff --git a/tests/ui/bool_comparison.fixed b/tests/ui/bool_comparison.fixed index 0bd73ec2c104..ccbbf950e830 100644 --- a/tests/ui/bool_comparison.fixed +++ b/tests/ui/bool_comparison.fixed @@ -111,3 +111,10 @@ fn issue3703() { if Foo < false {} if false < Foo {} } + +fn issue4983() { + let a = true; + let b = false; + + //if a == !b {}; +} diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index 74f504edfd06..f2e62d028f7a 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -111,3 +111,10 @@ fn issue3703() { if Foo < false {} if false < Foo {} } + +fn issue4983() { + let a = true; + let b = false; + + if a == !b {}; +} From 36ec41fe532ba883c45a63f68fbe951eb1e5faad Mon Sep 17 00:00:00 2001 From: mgr-inz-rafal Date: Tue, 4 Feb 2020 21:01:59 +0100 Subject: [PATCH 005/243] Detect offending comparison --- clippy_lints/src/needless_bool.rs | 31 +++++++++++++++++++++++-------- tests/ui/bool_comparison.rs | 3 +++ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 2814f0de7cfc..d0b89158f359 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -2,8 +2,9 @@ //! //! This lint is **warn** by default +use if_chain::if_chain; use crate::utils::sugg::Sugg; -use crate::utils::{higher, parent_node_is_if_expr, span_lint, span_lint_and_sugg}; +use crate::utils::{higher, parent_node_is_if_expr, span_lint, span_lint_and_help, span_lint_and_sugg}; use rustc_errors::Applicability; use rustc_hir::*; use rustc_lint::{LateContext, LateLintPass}; @@ -182,6 +183,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { } } +fn is_unary_not<'tcx>(e: &'tcx Expr<'_>) -> bool { + if_chain! { + if let ExprKind::Unary(unop, _) = e.kind; + if let UnOp::UnNot = unop; + then { + return true; + } + }; + false + } + +fn one_side_is_unary_not<'tcx>(left_side: &'tcx Expr<'_>, right_side: &'tcx Expr<'_>) -> bool { + is_unary_not(left_side) ^ is_unary_not(right_side) +} + fn check_comparison<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>, @@ -196,14 +212,13 @@ fn check_comparison<'a, 'tcx>( if let ExprKind::Binary(op, ref left_side, ref right_side) = e.kind { let (l_ty, r_ty) = (cx.tables.expr_ty(left_side), cx.tables.expr_ty(right_side)); if l_ty.is_bool() && r_ty.is_bool() { - if let BinOpKind::Eq = op.node { - if let ExprKind::Unary(unop, exx) = right_side.kind - { - if let UnOp::UnNot = unop { - // TODO: Lint here - } + if_chain! { + if let BinOpKind::Eq = op.node; + if one_side_is_unary_not(&left_side, &right_side); + then { + span_lint_and_help(cx, BOOL_COMPARISON, e.span, "help1", "help2"); } - } + }; let mut applicability = Applicability::MachineApplicable; match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index f2e62d028f7a..c13575eae717 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -117,4 +117,7 @@ fn issue4983() { let b = false; if a == !b {}; + if !a == b {}; + if a == b {}; + if !a == !b {}; } From 5fd22b3f93f6a23ff70024e27f4a13a41b610dfa Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 4 Feb 2020 16:07:09 +0100 Subject: [PATCH 006/243] Optionally indent snippet_block relative to an Expr --- clippy_lints/src/attrs.rs | 4 +- clippy_lints/src/collapsible_if.rs | 6 +- clippy_lints/src/matches.rs | 16 +++-- clippy_lints/src/utils/mod.rs | 105 ++++++++++++++++++++++------- 4 files changed, 96 insertions(+), 35 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 515e5af339bc..6f67acb29219 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -2,7 +2,7 @@ use crate::reexport::*; use crate::utils::{ - is_present_in_source, last_line_of_span, match_def_path, paths, snippet_opt, span_lint, span_lint_and_sugg, + first_line_of_span, is_present_in_source, match_def_path, paths, snippet_opt, span_lint, span_lint_and_sugg, span_lint_and_then, without_block_comments, }; use if_chain::if_chain; @@ -261,7 +261,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Attributes { _ => {}, } } - let line_span = last_line_of_span(cx, attr.span); + let line_span = first_line_of_span(cx, attr.span); if let Some(mut sugg) = snippet_opt(cx, line_span) { if sugg.contains("#[") { diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index af309b512699..c6ca85b0cdf4 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -95,7 +95,7 @@ fn check_if(cx: &EarlyContext<'_>, expr: &ast::Expr) { fn block_starts_with_comment(cx: &EarlyContext<'_>, expr: &ast::Block) -> bool { // We trim all opening braces and whitespaces and then check if the next string is a comment. - let trimmed_block_text = snippet_block(cx, expr.span, "..") + let trimmed_block_text = snippet_block(cx, expr.span, "..", None) .trim_start_matches(|c: char| c.is_whitespace() || c == '{') .to_owned(); trimmed_block_text.starts_with("//") || trimmed_block_text.starts_with("/*") @@ -116,7 +116,7 @@ fn check_collapsible_maybe_if_let(cx: &EarlyContext<'_>, else_: &ast::Expr) { block.span, "this `else { if .. }` block can be collapsed", "try", - snippet_block_with_applicability(cx, else_.span, "..", &mut applicability).into_owned(), + snippet_block_with_applicability(cx, else_.span, "..", Some(block.span), &mut applicability).into_owned(), applicability, ); } @@ -146,7 +146,7 @@ fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: & format!( "if {} {}", lhs.and(&rhs), - snippet_block(cx, content.span, ".."), + snippet_block(cx, content.span, "..", Some(expr.span)), ), Applicability::MachineApplicable, // snippet ); diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 1d8c5ec9038d..054535353470 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -434,7 +434,7 @@ fn report_single_match_single_pattern( ) { let lint = if els.is_some() { SINGLE_MATCH_ELSE } else { SINGLE_MATCH }; let els_str = els.map_or(String::new(), |els| { - format!(" else {}", expr_block(cx, els, None, "..")) + format!(" else {}", expr_block(cx, els, None, "..", Some(expr.span))) }); span_lint_and_sugg( cx, @@ -447,7 +447,7 @@ fn report_single_match_single_pattern( "if let {} = {} {}{}", snippet(cx, arms[0].pat.span, ".."), snippet(cx, ex.span, ".."), - expr_block(cx, &arms[0].body, None, ".."), + expr_block(cx, &arms[0].body, None, "..", Some(expr.span)), els_str, ), Applicability::HasPlaceholders, @@ -523,17 +523,21 @@ fn check_match_bool(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>], e (false, false) => Some(format!( "if {} {} else {}", snippet(cx, ex.span, "b"), - expr_block(cx, true_expr, None, ".."), - expr_block(cx, false_expr, None, "..") + expr_block(cx, true_expr, None, "..", Some(expr.span)), + expr_block(cx, false_expr, None, "..", Some(expr.span)) )), (false, true) => Some(format!( "if {} {}", snippet(cx, ex.span, "b"), - expr_block(cx, true_expr, None, "..") + expr_block(cx, true_expr, None, "..", Some(expr.span)) )), (true, false) => { let test = Sugg::hir(cx, ex, ".."); - Some(format!("if {} {}", !test, expr_block(cx, false_expr, None, ".."))) + Some(format!( + "if {} {}", + !test, + expr_block(cx, false_expr, None, "..", Some(expr.span)) + )) }, (true, true) => None, }; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 4b7e21bc3bad..e00c65569b3d 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -44,6 +44,7 @@ use rustc_hir::Node; use rustc_hir::*; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_span::hygiene::{ExpnKind, MacroKind}; +use rustc_span::source_map::original_sp; use rustc_span::symbol::{self, kw, Symbol}; use rustc_span::{BytePos, Pos, Span, DUMMY_SP}; use smallvec::SmallVec; @@ -541,11 +542,17 @@ pub fn snippet_opt(cx: &T, span: Span) -> Option { /// /// # Example /// ```rust,ignore -/// snippet_block(cx, expr.span, "..") +/// snippet_block(cx, expr.span, "..", None) /// ``` -pub fn snippet_block<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { +pub fn snippet_block<'a, T: LintContext>( + cx: &T, + span: Span, + default: &'a str, + indent_relative_to: Option, +) -> Cow<'a, str> { let snip = snippet(cx, span, default); - trim_multiline(snip, true) + let indent = indent_relative_to.and_then(|s| indent_of(cx, s)); + trim_multiline(snip, true, indent) } /// Same as `snippet_block`, but adapts the applicability level by the rules of @@ -554,27 +561,73 @@ pub fn snippet_block_with_applicability<'a, T: LintContext>( cx: &T, span: Span, default: &'a str, + indent_relative_to: Option, applicability: &mut Applicability, ) -> Cow<'a, str> { let snip = snippet_with_applicability(cx, span, default, applicability); - trim_multiline(snip, true) + let indent = indent_relative_to.and_then(|s| indent_of(cx, s)); + trim_multiline(snip, true, indent) } -/// Returns a new Span that covers the full last line of the given Span -pub fn last_line_of_span(cx: &T, span: Span) -> Span { +/// Returns a new Span that extends the original Span to the first non-whitespace char of the first +/// line. +/// +/// ```rust,ignore +/// let x = (); +/// // ^^ +/// // will be converted to +/// let x = (); +/// // ^^^^^^^^^^ +/// ``` +pub fn first_line_of_span(cx: &T, span: Span) -> Span { + if let Some(first_char_pos) = first_char_in_first_line(cx, span) { + span.with_lo(first_char_pos) + } else { + span + } +} + +fn first_char_in_first_line(cx: &T, span: Span) -> Option { + let line_span = line_span(cx, span); + if let Some(snip) = snippet_opt(cx, line_span) { + snip.find(|c: char| !c.is_whitespace()) + .map(|pos| line_span.lo() + BytePos::from_usize(pos)) + } else { + None + } +} + +/// Returns the indentation of the line of a span +/// +/// ```rust,ignore +/// let x = (); +/// // ^^ -- will return 0 +/// let x = (); +/// // ^^ -- will return 4 +/// ``` +pub fn indent_of(cx: &T, span: Span) -> Option { + if let Some(snip) = snippet_opt(cx, line_span(cx, span)) { + snip.find(|c: char| !c.is_whitespace()) + } else { + None + } +} + +/// Extends the span to the beginning of the spans line, incl. whitespaces. +/// +/// ```rust,ignore +/// let x = (); +/// // ^^ +/// // will be converted to +/// let x = (); +/// // ^^^^^^^^^^^^^^ +/// ``` +fn line_span(cx: &T, span: Span) -> Span { + let span = original_sp(span, DUMMY_SP); let source_map_and_line = cx.sess().source_map().lookup_line(span.lo()).unwrap(); let line_no = source_map_and_line.line; - let line_start = &source_map_and_line.sf.lines[line_no]; - let span = Span::new(*line_start, span.hi(), span.ctxt()); - if_chain! { - if let Some(snip) = snippet_opt(cx, span); - if let Some(first_ch_pos) = snip.find(|c: char| !c.is_whitespace()); - then { - span.with_lo(span.lo() + BytePos::from_usize(first_ch_pos)) - } else { - span - } - } + let line_start = source_map_and_line.sf.lines[line_no]; + Span::new(line_start, span.hi(), span.ctxt()) } /// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`. @@ -584,8 +637,9 @@ pub fn expr_block<'a, T: LintContext>( expr: &Expr<'_>, option: Option, default: &'a str, + indent_relative_to: Option, ) -> Cow<'a, str> { - let code = snippet_block(cx, expr.span, default); + let code = snippet_block(cx, expr.span, default, indent_relative_to); let string = option.unwrap_or_default(); if expr.span.from_expansion() { Cow::Owned(format!("{{ {} }}", snippet_with_macro_callsite(cx, expr.span, default))) @@ -600,14 +654,14 @@ pub fn expr_block<'a, T: LintContext>( /// Trim indentation from a multiline string with possibility of ignoring the /// first line. -pub fn trim_multiline(s: Cow<'_, str>, ignore_first: bool) -> Cow<'_, str> { - let s_space = trim_multiline_inner(s, ignore_first, ' '); - let s_tab = trim_multiline_inner(s_space, ignore_first, '\t'); - trim_multiline_inner(s_tab, ignore_first, ' ') +pub fn trim_multiline(s: Cow<'_, str>, ignore_first: bool, indent: Option) -> Cow<'_, str> { + let s_space = trim_multiline_inner(s, ignore_first, indent, ' '); + let s_tab = trim_multiline_inner(s_space, ignore_first, indent, '\t'); + trim_multiline_inner(s_tab, ignore_first, indent, ' ') } -fn trim_multiline_inner(s: Cow<'_, str>, ignore_first: bool, ch: char) -> Cow<'_, str> { - let x = s +fn trim_multiline_inner(s: Cow<'_, str>, ignore_first: bool, indent: Option, ch: char) -> Cow<'_, str> { + let mut x = s .lines() .skip(ignore_first as usize) .filter_map(|l| { @@ -620,6 +674,9 @@ fn trim_multiline_inner(s: Cow<'_, str>, ignore_first: bool, ch: char) -> Cow<'_ }) .min() .unwrap_or(0); + if let Some(indent) = indent { + x = x.saturating_sub(indent); + } if x > 0 { Cow::Owned( s.lines() From 19f08c200e25ac7c9029594476a382b2bf82e00a Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 4 Feb 2020 16:08:15 +0100 Subject: [PATCH 007/243] Make block_in_if_condition auto applicable --- clippy_lints/src/block_in_if_condition.rs | 47 +++++++++++++++-------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 5a64e444136e..325e12617142 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -2,6 +2,7 @@ use crate::utils::*; use matches::matches; use rustc::hir::map::Map; use rustc::lint::in_external_macro; +use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::*; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -79,8 +80,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { if in_external_macro(cx.sess(), expr.span) { return; } - if let Some((check, then, _)) = higher::if_block(&expr) { - if let ExprKind::Block(block, _) = &check.kind { + if let Some((cond, _, _)) = higher::if_block(&expr) { + if let ExprKind::Block(block, _) = &cond.kind { if block.rules == BlockCheckMode::DefaultBlock { if block.stmts.is_empty() { if let Some(ex) = &block.expr { @@ -89,16 +90,24 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { if expr.span.from_expansion() || differing_macro_contexts(expr.span, ex.span) { return; } - span_lint_and_help( + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( cx, BLOCK_IN_IF_CONDITION_EXPR, - check.span, + cond.span, BRACED_EXPR_MESSAGE, - &format!( - "try\nif {} {} ... ", - snippet_block(cx, ex.span, ".."), - snippet_block(cx, then.span, "..") + "try", + format!( + "{}", + snippet_block_with_applicability( + cx, + ex.span, + "..", + Some(expr.span), + &mut applicability + ) ), + applicability, ); } } else { @@ -107,22 +116,30 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition { return; } // move block higher - span_lint_and_help( + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( cx, BLOCK_IN_IF_CONDITION_STMT, - check.span, + expr.span.with_hi(cond.span.hi()), COMPLEX_BLOCK_MESSAGE, - &format!( - "try\nlet res = {};\nif res {} ... ", - snippet_block(cx, block.span, ".."), - snippet_block(cx, then.span, "..") + "try", + format!( + "let res = {}; if res", + snippet_block_with_applicability( + cx, + block.span, + "..", + Some(expr.span), + &mut applicability + ), ), + applicability, ); } } } else { let mut visitor = ExVisitor { found_block: None, cx }; - walk_expr(&mut visitor, check); + walk_expr(&mut visitor, cond); if let Some(block) = visitor.found_block { span_lint(cx, BLOCK_IN_IF_CONDITION_STMT, block.span, COMPLEX_BLOCK_MESSAGE); } From 10cd1662c145a52ca6fe5d5e86ee117652598bc2 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 4 Feb 2020 16:08:39 +0100 Subject: [PATCH 008/243] Update block_in_if_condition test files --- tests/ui/block_in_if_condition.fixed | 75 +++++++++++++++++++ tests/ui/block_in_if_condition.rs | 48 +----------- tests/ui/block_in_if_condition.stderr | 52 ++++--------- tests/ui/block_in_if_condition_closure.rs | 48 ++++++++++++ tests/ui/block_in_if_condition_closure.stderr | 24 ++++++ 5 files changed, 163 insertions(+), 84 deletions(-) create mode 100644 tests/ui/block_in_if_condition.fixed create mode 100644 tests/ui/block_in_if_condition_closure.rs create mode 100644 tests/ui/block_in_if_condition_closure.stderr diff --git a/tests/ui/block_in_if_condition.fixed b/tests/ui/block_in_if_condition.fixed new file mode 100644 index 000000000000..955801e40f9b --- /dev/null +++ b/tests/ui/block_in_if_condition.fixed @@ -0,0 +1,75 @@ +// run-rustfix +#![warn(clippy::block_in_if_condition_expr)] +#![warn(clippy::block_in_if_condition_stmt)] +#![allow(unused, clippy::let_and_return)] +#![warn(clippy::nonminimal_bool)] + +macro_rules! blocky { + () => {{ + true + }}; +} + +macro_rules! blocky_too { + () => {{ + let r = true; + r + }}; +} + +fn macro_if() { + if blocky!() {} + + if blocky_too!() {} +} + +fn condition_has_block() -> i32 { + let res = { + let x = 3; + x == 3 + }; if res { + 6 + } else { + 10 + } +} + +fn condition_has_block_with_single_expression() -> i32 { + if true { + 6 + } else { + 10 + } +} + +fn condition_is_normal() -> i32 { + let x = 3; + if x == 3 { + 6 + } else { + 10 + } +} + +fn condition_is_unsafe_block() { + let a: i32 = 1; + + // this should not warn because the condition is an unsafe block + if unsafe { 1u32 == std::mem::transmute(a) } { + println!("1u32 == a"); + } +} + +fn block_in_assert() { + let opt = Some(42); + assert!(opt + .as_ref() + .and_then(|val| { + let mut v = val * 2; + v -= 1; + Some(v * 3) + }) + .is_some()); +} + +fn main() {} diff --git a/tests/ui/block_in_if_condition.rs b/tests/ui/block_in_if_condition.rs index 50f238814a31..a6ea01d5fc5f 100644 --- a/tests/ui/block_in_if_condition.rs +++ b/tests/ui/block_in_if_condition.rs @@ -1,3 +1,4 @@ +// run-rustfix #![warn(clippy::block_in_if_condition_expr)] #![warn(clippy::block_in_if_condition_stmt)] #![allow(unused, clippy::let_and_return)] @@ -41,37 +42,6 @@ fn condition_has_block_with_single_expression() -> i32 { } } -fn predicate bool, T>(pfn: F, val: T) -> bool { - pfn(val) -} - -fn pred_test() { - let v = 3; - let sky = "blue"; - // This is a sneaky case, where the block isn't directly in the condition, - // but is actually nside a closure that the condition is using. - // The same principle applies -- add some extra expressions to make sure - // linter isn't confused by them. - if v == 3 - && sky == "blue" - && predicate( - |x| { - let target = 3; - x == target - }, - v, - ) - {} - - if predicate( - |x| { - let target = 3; - x == target - }, - v, - ) {} -} - fn condition_is_normal() -> i32 { let x = 3; if true && x == 3 { @@ -81,10 +51,6 @@ fn condition_is_normal() -> i32 { } } -fn closure_without_block() { - if predicate(|x| x == 3, 6) {} -} - fn condition_is_unsafe_block() { let a: i32 = 1; @@ -94,16 +60,6 @@ fn condition_is_unsafe_block() { } } -fn main() {} - -fn macro_in_closure() { - let option = Some(true); - - if option.unwrap_or_else(|| unimplemented!()) { - unimplemented!() - } -} - fn block_in_assert() { let opt = Some(42); assert!(opt @@ -115,3 +71,5 @@ fn block_in_assert() { }) .is_some()); } + +fn main() {} diff --git a/tests/ui/block_in_if_condition.stderr b/tests/ui/block_in_if_condition.stderr index d75f3c02f197..b0a0a276c890 100644 --- a/tests/ui/block_in_if_condition.stderr +++ b/tests/ui/block_in_if_condition.stderr @@ -1,62 +1,36 @@ error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` - --> $DIR/block_in_if_condition.rs:26:8 + --> $DIR/block_in_if_condition.rs:27:5 | -LL | if { - | ________^ +LL | / if { LL | | let x = 3; LL | | x == 3 LL | | } { | |_____^ | = note: `-D clippy::block-in-if-condition-stmt` implied by `-D warnings` - = help: try - let res = { - let x = 3; - x == 3 - }; - if res { - 6 - } ... +help: try + | +LL | let res = { +LL | let x = 3; +LL | x == 3 +LL | }; if res { + | error: omit braces around single expression condition - --> $DIR/block_in_if_condition.rs:37:8 + --> $DIR/block_in_if_condition.rs:38:8 | LL | if { true } { - | ^^^^^^^^ + | ^^^^^^^^ help: try: `true` | = note: `-D clippy::block-in-if-condition-expr` implied by `-D warnings` - = help: try - if true { - 6 - } ... - -error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` - --> $DIR/block_in_if_condition.rs:58:17 - | -LL | |x| { - | _________________^ -LL | | let target = 3; -LL | | x == target -LL | | }, - | |_____________^ - -error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` - --> $DIR/block_in_if_condition.rs:67:13 - | -LL | |x| { - | _____________^ -LL | | let target = 3; -LL | | x == target -LL | | }, - | |_________^ error: this boolean expression can be simplified - --> $DIR/block_in_if_condition.rs:77:8 + --> $DIR/block_in_if_condition.rs:47:8 | LL | if true && x == 3 { | ^^^^^^^^^^^^^^ help: try: `x == 3` | = note: `-D clippy::nonminimal-bool` implied by `-D warnings` -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/block_in_if_condition_closure.rs b/tests/ui/block_in_if_condition_closure.rs new file mode 100644 index 000000000000..bac3eda5e7f3 --- /dev/null +++ b/tests/ui/block_in_if_condition_closure.rs @@ -0,0 +1,48 @@ +#![warn(clippy::block_in_if_condition_expr)] +#![warn(clippy::block_in_if_condition_stmt)] +#![allow(unused, clippy::let_and_return)] + +fn predicate bool, T>(pfn: F, val: T) -> bool { + pfn(val) +} + +fn pred_test() { + let v = 3; + let sky = "blue"; + // This is a sneaky case, where the block isn't directly in the condition, + // but is actually nside a closure that the condition is using. + // The same principle applies -- add some extra expressions to make sure + // linter isn't confused by them. + if v == 3 + && sky == "blue" + && predicate( + |x| { + let target = 3; + x == target + }, + v, + ) + {} + + if predicate( + |x| { + let target = 3; + x == target + }, + v, + ) {} +} + +fn closure_without_block() { + if predicate(|x| x == 3, 6) {} +} + +fn macro_in_closure() { + let option = Some(true); + + if option.unwrap_or_else(|| unimplemented!()) { + unimplemented!() + } +} + +fn main() {} diff --git a/tests/ui/block_in_if_condition_closure.stderr b/tests/ui/block_in_if_condition_closure.stderr new file mode 100644 index 000000000000..86cd24fe7632 --- /dev/null +++ b/tests/ui/block_in_if_condition_closure.stderr @@ -0,0 +1,24 @@ +error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` + --> $DIR/block_in_if_condition_closure.rs:19:17 + | +LL | |x| { + | _________________^ +LL | | let target = 3; +LL | | x == target +LL | | }, + | |_____________^ + | + = note: `-D clippy::block-in-if-condition-stmt` implied by `-D warnings` + +error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` + --> $DIR/block_in_if_condition_closure.rs:28:13 + | +LL | |x| { + | _____________^ +LL | | let target = 3; +LL | | x == target +LL | | }, + | |_________^ + +error: aborting due to 2 previous errors + From 8e15985827ebf0ebf084efeb3d17a8cd25e99242 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 4 Feb 2020 16:10:59 +0100 Subject: [PATCH 009/243] Rewrite suggestion generation of needless_continue --- clippy_lints/src/needless_continue.rs | 163 +++++++++++++------------- tests/needless_continue_helpers.rs | 87 -------------- 2 files changed, 84 insertions(+), 166 deletions(-) delete mode 100644 tests/needless_continue_helpers.rs diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index ac14b113cc58..75cbfe13072e 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -36,10 +36,10 @@ use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::{original_sp, DUMMY_SP}; -use std::borrow::Cow; +use rustc_span::Span; use syntax::ast; -use crate::utils::{snippet, snippet_block, span_lint_and_help, trim_multiline}; +use crate::utils::{indent_of, snippet, snippet_block, span_lint_and_help}; declare_clippy_lint! { /// **What it does:** The lint checks for `if`-statements appearing in loops @@ -273,16 +273,15 @@ struct LintData<'a> { block_stmts: &'a [ast::Stmt], } -const MSG_REDUNDANT_ELSE_BLOCK: &str = "This `else` block is redundant.\n"; +const MSG_REDUNDANT_ELSE_BLOCK: &str = "this `else` block is redundant"; -const MSG_ELSE_BLOCK_NOT_NEEDED: &str = "There is no need for an explicit `else` block for this `if` \ - expression\n"; +const MSG_ELSE_BLOCK_NOT_NEEDED: &str = "there is no need for an explicit `else` block for this `if` \ + expression"; -const DROP_ELSE_BLOCK_AND_MERGE_MSG: &str = "Consider dropping the `else` clause and merging the code that \ - follows (in the loop) with the `if` block, like so:\n"; +const DROP_ELSE_BLOCK_AND_MERGE_MSG: &str = "consider dropping the `else` clause and merging the code that \ + follows (in the loop) with the `if` block"; -const DROP_ELSE_BLOCK_MSG: &str = "Consider dropping the `else` clause, and moving out the code in the `else` \ - block, like so:\n"; +const DROP_ELSE_BLOCK_MSG: &str = "consider dropping the `else` clause"; fn emit_warning<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str, typ: LintType) { // snip is the whole *help* message that appears after the warning. @@ -290,73 +289,77 @@ fn emit_warning<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str // expr is the expression which the lint warning message refers to. let (snip, message, expr) = match typ { LintType::ContinueInsideElseBlock => ( - suggestion_snippet_for_continue_inside_else(ctx, data, header), + suggestion_snippet_for_continue_inside_else(ctx, data), MSG_REDUNDANT_ELSE_BLOCK, data.else_expr, ), LintType::ContinueInsideThenBlock => ( - suggestion_snippet_for_continue_inside_if(ctx, data, header), + suggestion_snippet_for_continue_inside_if(ctx, data), MSG_ELSE_BLOCK_NOT_NEEDED, data.if_expr, ), }; - span_lint_and_help(ctx, NEEDLESS_CONTINUE, expr.span, message, &snip); + span_lint_and_help( + ctx, + NEEDLESS_CONTINUE, + expr.span, + message, + &format!("{}\n{}", header, snip), + ); } -fn suggestion_snippet_for_continue_inside_if<'a>( - ctx: &EarlyContext<'_>, - data: &'a LintData<'_>, - header: &str, -) -> String { +fn suggestion_snippet_for_continue_inside_if<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>) -> String { let cond_code = snippet(ctx, data.if_cond.span, ".."); - let if_code = format!("if {} {{\n continue;\n}}\n", cond_code); - /* ^^^^--- Four spaces of indentation. */ + let continue_code = snippet_block(ctx, data.if_block.span, "..", Some(data.if_expr.span)); // region B - let else_code = snippet(ctx, data.else_expr.span, "..").into_owned(); - let else_code = erode_block(&else_code); - let else_code = trim_multiline(Cow::from(else_code), false); + let else_code = snippet_block(ctx, data.else_expr.span, "..", Some(data.if_expr.span)); - let mut ret = String::from(header); - ret.push_str(&if_code); - ret.push_str(&else_code); - ret.push_str("\n..."); - ret + let indent_if = indent_of(ctx, data.if_expr.span).unwrap_or(0); + format!( + "{}if {} {} {}", + " ".repeat(indent_if), + cond_code, + continue_code, + else_code, + ) } -fn suggestion_snippet_for_continue_inside_else<'a>( - ctx: &EarlyContext<'_>, - data: &'a LintData<'_>, - header: &str, -) -> String { +fn suggestion_snippet_for_continue_inside_else<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>) -> String { let cond_code = snippet(ctx, data.if_cond.span, ".."); - let mut if_code = format!("if {} {{\n", cond_code); // Region B - let block_code = &snippet(ctx, data.if_block.span, "..").into_owned(); - let block_code = erode_block(block_code); - let block_code = trim_multiline(Cow::from(block_code), false); - - if_code.push_str(&block_code); + let block_code = erode_from_back(&snippet_block(ctx, data.if_block.span, "..", Some(data.if_expr.span))); // Region C // These is the code in the loop block that follows the if/else construction // we are complaining about. We want to pull all of this code into the // `then` block of the `if` statement. + let indent = span_of_first_expr_in_block(data.if_block) + .and_then(|span| indent_of(ctx, span)) + .unwrap_or(0); let to_annex = data.block_stmts[data.stmt_idx + 1..] .iter() .map(|stmt| original_sp(stmt.span, DUMMY_SP)) - .map(|span| snippet_block(ctx, span, "..").into_owned()) + .map(|span| { + let snip = snippet_block(ctx, span, "..", None).into_owned(); + snip.lines() + .map(|line| format!("{}{}", " ".repeat(indent), line)) + .collect::>() + .join("\n") + }) .collect::>() .join("\n"); - let mut ret = String::from(header); - - ret.push_str(&if_code); - ret.push_str("\n// Merged code follows..."); - ret.push_str(&to_annex); - ret.push_str("\n}\n"); - ret + let indent_if = indent_of(ctx, data.if_expr.span).unwrap_or(0); + format!( + "{indent_if}if {} {}\n{indent}// merged code follows:\n{}\n{indent_if}}}", + cond_code, + block_code, + to_annex, + indent = " ".repeat(indent), + indent_if = " ".repeat(indent_if), + ) } fn check_and_warn<'a>(ctx: &EarlyContext<'_>, expr: &'a ast::Expr) { @@ -406,7 +409,7 @@ fn check_and_warn<'a>(ctx: &EarlyContext<'_>, expr: &'a ast::Expr) { /// NOTE: when there is no closing brace in `s`, `s` is _not_ preserved, i.e., /// an empty string will be returned in that case. #[must_use] -pub fn erode_from_back(s: &str) -> String { +fn erode_from_back(s: &str) -> String { let mut ret = String::from(s); while ret.pop().map_or(false, |c| c != '}') {} while let Some(c) = ret.pop() { @@ -418,38 +421,40 @@ pub fn erode_from_back(s: &str) -> String { ret } -/// Eats at `s` from the front by first skipping all leading whitespace. Then, -/// any number of opening braces are eaten, followed by any number of newlines. -/// e.g., the string -/// -/// ```ignore -/// { -/// something(); -/// inside_a_block(); -/// } -/// ``` -/// -/// is transformed to -/// -/// ```ignore -/// something(); -/// inside_a_block(); -/// } -/// ``` -#[must_use] -pub fn erode_from_front(s: &str) -> String { - s.chars() - .skip_while(|c| c.is_whitespace()) - .skip_while(|c| *c == '{') - .skip_while(|c| *c == '\n') - .collect::() +fn span_of_first_expr_in_block(block: &ast::Block) -> Option { + block.stmts.iter().next().map(|stmt| stmt.span) } -/// If `s` contains the code for a block, delimited by braces, this function -/// tries to get the contents of the block. If there is no closing brace -/// present, -/// an empty string is returned. -#[must_use] -pub fn erode_block(s: &str) -> String { - erode_from_back(&erode_from_front(s)) +#[cfg(test)] +mod test { + use super::erode_from_back; + #[test] + #[rustfmt::skip] + fn test_erode_from_back() { + let input = "\ +{ + let x = 5; + let y = format!(\"{}\", 42); +}"; + + let expected = "\ +{ + let x = 5; + let y = format!(\"{}\", 42);"; + + let got = erode_from_back(input); + assert_eq!(expected, got); + } + + #[test] + #[rustfmt::skip] + fn test_erode_from_back_no_brace() { + let input = "\ +let x = 5; +let y = something(); +"; + let expected = ""; + let got = erode_from_back(input); + assert_eq!(expected, got); + } } diff --git a/tests/needless_continue_helpers.rs b/tests/needless_continue_helpers.rs deleted file mode 100644 index 255653b4737d..000000000000 --- a/tests/needless_continue_helpers.rs +++ /dev/null @@ -1,87 +0,0 @@ -// Tests for the various helper functions used by the needless_continue -// lint that don't belong in utils. - -use clippy_lints::needless_continue::{erode_block, erode_from_back, erode_from_front}; - -#[test] -#[rustfmt::skip] -fn test_erode_from_back() { - let input = "\ -{ - let x = 5; - let y = format!(\"{}\", 42); -}"; - - let expected = "\ -{ - let x = 5; - let y = format!(\"{}\", 42);"; - - let got = erode_from_back(input); - assert_eq!(expected, got); -} - -#[test] -#[rustfmt::skip] -fn test_erode_from_back_no_brace() { - let input = "\ -let x = 5; -let y = something(); -"; - let expected = ""; - let got = erode_from_back(input); - assert_eq!(expected, got); -} - -#[test] -#[rustfmt::skip] -fn test_erode_from_front() { - let input = " - { - something(); - inside_a_block(); - } - "; - let expected = -" something(); - inside_a_block(); - } - "; - let got = erode_from_front(input); - println!("input: {}\nexpected:\n{}\ngot:\n{}", input, expected, got); - assert_eq!(expected, got); -} - -#[test] -#[rustfmt::skip] -fn test_erode_from_front_no_brace() { - let input = " - something(); - inside_a_block(); - "; - let expected = -"something(); - inside_a_block(); - "; - let got = erode_from_front(input); - println!("input: {}\nexpected:\n{}\ngot:\n{}", input, expected, got); - assert_eq!(expected, got); -} - -#[test] -#[rustfmt::skip] -fn test_erode_block() { - - let input = " - { - something(); - inside_a_block(); - } - "; - let expected = -" something(); - inside_a_block();"; - let got = erode_block(input); - println!("input: {}\nexpected:\n{}\ngot:\n{}", input, expected, got); - assert_eq!(expected, got); -} From f1a72e992d75983e1a2503b4e577971d7e018f1d Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 4 Feb 2020 16:11:49 +0100 Subject: [PATCH 010/243] Update needless_continue stderr --- clippy_lints/src/utils/mod.rs | 2 +- tests/ui/needless_continue.stderr | 114 ++++++++++++++---------------- 2 files changed, 56 insertions(+), 60 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index e00c65569b3d..4b3c84505aa5 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -654,7 +654,7 @@ pub fn expr_block<'a, T: LintContext>( /// Trim indentation from a multiline string with possibility of ignoring the /// first line. -pub fn trim_multiline(s: Cow<'_, str>, ignore_first: bool, indent: Option) -> Cow<'_, str> { +fn trim_multiline(s: Cow<'_, str>, ignore_first: bool, indent: Option) -> Cow<'_, str> { let s_space = trim_multiline_inner(s, ignore_first, indent, ' '); let s_tab = trim_multiline_inner(s_space, ignore_first, indent, '\t'); trim_multiline_inner(s_tab, ignore_first, indent, ' ') diff --git a/tests/ui/needless_continue.stderr b/tests/ui/needless_continue.stderr index b9215885877d..6c4aa7445203 100644 --- a/tests/ui/needless_continue.stderr +++ b/tests/ui/needless_continue.stderr @@ -1,5 +1,4 @@ -error: This `else` block is redundant. - +error: this `else` block is redundant --> $DIR/needless_continue.rs:28:16 | LL | } else { @@ -9,34 +8,33 @@ LL | | } | |_________^ | = note: `-D clippy::needless-continue` implied by `-D warnings` - = help: Consider dropping the `else` clause and merging the code that follows (in the loop) with the `if` block, like so: - if i % 2 == 0 && i % 3 == 0 { - println!("{}", i); - println!("{}", i + 1); - if i % 5 == 0 { - println!("{}", i + 2); - } - let i = 0; - println!("bar {} ", i); - // Merged code follows...println!("bleh"); - { - println!("blah"); - } - if !(!(i == 2) || !(i == 5)) { - println!("lama"); - } - if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 { - continue; - } else { - println!("Blabber"); - println!("Jabber"); - } - println!("bleh"); - } - - -error: There is no need for an explicit `else` block for this `if` expression + = help: consider dropping the `else` clause and merging the code that follows (in the loop) with the `if` block + if i % 2 == 0 && i % 3 == 0 { + println!("{}", i); + println!("{}", i + 1); + if i % 5 == 0 { + println!("{}", i + 2); + } + let i = 0; + println!("bar {} ", i); + // merged code follows: + println!("bleh"); + { + println!("blah"); + } + if !(!(i == 2) || !(i == 5)) { + println!("lama"); + } + if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 { + continue; + } else { + println!("Blabber"); + println!("Jabber"); + } + println!("bleh"); + } +error: there is no need for an explicit `else` block for this `if` expression --> $DIR/needless_continue.rs:43:9 | LL | / if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 { @@ -47,16 +45,15 @@ LL | | println!("Jabber"); LL | | } | |_________^ | - = help: Consider dropping the `else` clause, and moving out the code in the `else` block, like so: - if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 { - continue; - } - println!("Blabber"); - println!("Jabber"); - ... - -error: This `else` block is redundant. + = help: consider dropping the `else` clause + if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 { + continue; + } { + println!("Blabber"); + println!("Jabber"); + } +error: this `else` block is redundant --> $DIR/needless_continue.rs:100:24 | LL | } else { @@ -65,22 +62,21 @@ LL | | continue 'inner; // should lint here LL | | } | |_________________^ | - = help: Consider dropping the `else` clause and merging the code that follows (in the loop) with the `if` block, like so: - if condition() { - println!("bar-3"); - // Merged code follows...println!("bar-4"); - update_condition(); - if condition() { - continue; // should lint here - } else { - println!("bar-5"); - } - println!("bar-6"); - } - - -error: There is no need for an explicit `else` block for this `if` expression + = help: consider dropping the `else` clause and merging the code that follows (in the loop) with the `if` block + if condition() { + println!("bar-3"); + // merged code follows: + println!("bar-4"); + update_condition(); + if condition() { + continue; // should lint here + } else { + println!("bar-5"); + } + println!("bar-6"); + } +error: there is no need for an explicit `else` block for this `if` expression --> $DIR/needless_continue.rs:106:17 | LL | / if condition() { @@ -90,12 +86,12 @@ LL | | println!("bar-5"); LL | | } | |_________________^ | - = help: Consider dropping the `else` clause, and moving out the code in the `else` block, like so: - if condition() { - continue; - } - println!("bar-5"); - ... + = help: consider dropping the `else` clause + if condition() { + continue; // should lint here + } { + println!("bar-5"); + } error: aborting due to 4 previous errors From cd0f0946cf01cb676b734379d27069b16b59a444 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 4 Feb 2020 16:12:51 +0100 Subject: [PATCH 011/243] Move tests to the end of the file in utils mod.rs --- clippy_lints/src/utils/mod.rs | 162 +++++++++++++++++----------------- 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 4b3c84505aa5..b9a62382aa39 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1198,87 +1198,6 @@ pub fn is_normalizable<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, param_env: ty::Para }) } -#[cfg(test)] -mod test { - use super::{trim_multiline, without_block_comments}; - - #[test] - fn test_trim_multiline_single_line() { - assert_eq!("", trim_multiline("".into(), false)); - assert_eq!("...", trim_multiline("...".into(), false)); - assert_eq!("...", trim_multiline(" ...".into(), false)); - assert_eq!("...", trim_multiline("\t...".into(), false)); - assert_eq!("...", trim_multiline("\t\t...".into(), false)); - } - - #[test] - #[rustfmt::skip] - fn test_trim_multiline_block() { - assert_eq!("\ - if x { - y - } else { - z - }", trim_multiline(" if x { - y - } else { - z - }".into(), false)); - assert_eq!("\ - if x { - \ty - } else { - \tz - }", trim_multiline(" if x { - \ty - } else { - \tz - }".into(), false)); - } - - #[test] - #[rustfmt::skip] - fn test_trim_multiline_empty_line() { - assert_eq!("\ - if x { - y - - } else { - z - }", trim_multiline(" if x { - y - - } else { - z - }".into(), false)); - } - - #[test] - fn test_without_block_comments_lines_without_block_comments() { - let result = without_block_comments(vec!["/*", "", "*/"]); - println!("result: {:?}", result); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""]); - assert_eq!(result, vec!["", "#[crate_type = \"lib\"]", ""]); - - let result = without_block_comments(vec!["/* rust", "", "*/"]); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["/* one-line comment */"]); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["/* nested", "/* multi-line", "comment", "*/", "test", "*/"]); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["/* nested /* inline /* comment */ test */ */"]); - assert!(result.is_empty()); - - let result = without_block_comments(vec!["foo", "bar", "baz"]); - assert_eq!(result, vec!["foo", "bar", "baz"]); - } -} - pub fn match_def_path<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, did: DefId, syms: &[&str]) -> bool { let path = cx.get_def_path(did); path.len() == syms.len() && path.into_iter().zip(syms.iter()).all(|(a, &b)| a.as_str() == b) @@ -1426,3 +1345,84 @@ pub fn is_trait_impl_item(cx: &LateContext<'_, '_>, hir_id: HirId) -> bool { false } } + +#[cfg(test)] +mod test { + use super::{trim_multiline, without_block_comments}; + + #[test] + fn test_trim_multiline_single_line() { + assert_eq!("", trim_multiline("".into(), false, None)); + assert_eq!("...", trim_multiline("...".into(), false, None)); + assert_eq!("...", trim_multiline(" ...".into(), false, None)); + assert_eq!("...", trim_multiline("\t...".into(), false, None)); + assert_eq!("...", trim_multiline("\t\t...".into(), false, None)); + } + + #[test] + #[rustfmt::skip] + fn test_trim_multiline_block() { + assert_eq!("\ + if x { + y + } else { + z + }", trim_multiline(" if x { + y + } else { + z + }".into(), false, None)); + assert_eq!("\ + if x { + \ty + } else { + \tz + }", trim_multiline(" if x { + \ty + } else { + \tz + }".into(), false, None)); + } + + #[test] + #[rustfmt::skip] + fn test_trim_multiline_empty_line() { + assert_eq!("\ + if x { + y + + } else { + z + }", trim_multiline(" if x { + y + + } else { + z + }".into(), false, None)); + } + + #[test] + fn test_without_block_comments_lines_without_block_comments() { + let result = without_block_comments(vec!["/*", "", "*/"]); + println!("result: {:?}", result); + assert!(result.is_empty()); + + let result = without_block_comments(vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""]); + assert_eq!(result, vec!["", "#[crate_type = \"lib\"]", ""]); + + let result = without_block_comments(vec!["/* rust", "", "*/"]); + assert!(result.is_empty()); + + let result = without_block_comments(vec!["/* one-line comment */"]); + assert!(result.is_empty()); + + let result = without_block_comments(vec!["/* nested", "/* multi-line", "comment", "*/", "test", "*/"]); + assert!(result.is_empty()); + + let result = without_block_comments(vec!["/* nested /* inline /* comment */ test */ */"]); + assert!(result.is_empty()); + + let result = without_block_comments(vec!["foo", "bar", "baz"]); + assert_eq!(result, vec!["foo", "bar", "baz"]); + } +} From 7363728d18659c695453cc6f6923c70a2554b1d4 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 4 Feb 2020 16:13:06 +0100 Subject: [PATCH 012/243] Update remaining test files --- tests/ui/collapsible_else_if.fixed | 58 ++++++++++++++--------------- tests/ui/collapsible_else_if.stderr | 58 ++++++++++++++--------------- tests/ui/collapsible_if.fixed | 28 +++++++------- tests/ui/collapsible_if.stderr | 28 +++++++------- tests/ui/match_bool.stderr | 20 +++++----- tests/ui/single_match.stderr | 4 +- tests/ui/single_match_else.stderr | 6 +-- 7 files changed, 101 insertions(+), 101 deletions(-) diff --git a/tests/ui/collapsible_else_if.fixed b/tests/ui/collapsible_else_if.fixed index a31f748670ce..c4149ad19c1e 100644 --- a/tests/ui/collapsible_else_if.fixed +++ b/tests/ui/collapsible_else_if.fixed @@ -10,57 +10,57 @@ fn main() { if x == "hello" { print!("Hello "); } else if y == "world" { - println!("world!") -} + println!("world!") + } if x == "hello" { print!("Hello "); } else if let Some(42) = Some(42) { - println!("world!") -} + println!("world!") + } if x == "hello" { print!("Hello "); } else if y == "world" { - println!("world") -} -else { - println!("!") -} + println!("world") + } + else { + println!("!") + } if x == "hello" { print!("Hello "); } else if let Some(42) = Some(42) { - println!("world") -} -else { - println!("!") -} + println!("world") + } + else { + println!("!") + } if let Some(42) = Some(42) { print!("Hello "); } else if let Some(42) = Some(42) { - println!("world") -} -else { - println!("!") -} + println!("world") + } + else { + println!("!") + } if let Some(42) = Some(42) { print!("Hello "); } else if x == "hello" { - println!("world") -} -else { - println!("!") -} + println!("world") + } + else { + println!("!") + } if let Some(42) = Some(42) { print!("Hello "); } else if let Some(42) = Some(42) { - println!("world") -} -else { - println!("!") -} + println!("world") + } + else { + println!("!") + } } diff --git a/tests/ui/collapsible_else_if.stderr b/tests/ui/collapsible_else_if.stderr index 26e3635c2d1c..28048999e8ec 100644 --- a/tests/ui/collapsible_else_if.stderr +++ b/tests/ui/collapsible_else_if.stderr @@ -13,8 +13,8 @@ LL | | } help: try | LL | } else if y == "world" { -LL | println!("world!") -LL | } +LL | println!("world!") +LL | } | error: this `else { if .. }` block can be collapsed @@ -31,8 +31,8 @@ LL | | } help: try | LL | } else if let Some(42) = Some(42) { -LL | println!("world!") -LL | } +LL | println!("world!") +LL | } | error: this `else { if .. }` block can be collapsed @@ -51,11 +51,11 @@ LL | | } help: try | LL | } else if y == "world" { -LL | println!("world") -LL | } -LL | else { -LL | println!("!") -LL | } +LL | println!("world") +LL | } +LL | else { +LL | println!("!") +LL | } | error: this `else { if .. }` block can be collapsed @@ -74,11 +74,11 @@ LL | | } help: try | LL | } else if let Some(42) = Some(42) { -LL | println!("world") -LL | } -LL | else { -LL | println!("!") -LL | } +LL | println!("world") +LL | } +LL | else { +LL | println!("!") +LL | } | error: this `else { if .. }` block can be collapsed @@ -97,11 +97,11 @@ LL | | } help: try | LL | } else if let Some(42) = Some(42) { -LL | println!("world") -LL | } -LL | else { -LL | println!("!") -LL | } +LL | println!("world") +LL | } +LL | else { +LL | println!("!") +LL | } | error: this `else { if .. }` block can be collapsed @@ -120,11 +120,11 @@ LL | | } help: try | LL | } else if x == "hello" { -LL | println!("world") -LL | } -LL | else { -LL | println!("!") -LL | } +LL | println!("world") +LL | } +LL | else { +LL | println!("!") +LL | } | error: this `else { if .. }` block can be collapsed @@ -143,11 +143,11 @@ LL | | } help: try | LL | } else if let Some(42) = Some(42) { -LL | println!("world") -LL | } -LL | else { -LL | println!("!") -LL | } +LL | println!("world") +LL | } +LL | else { +LL | println!("!") +LL | } | error: aborting due to 7 previous errors diff --git a/tests/ui/collapsible_if.fixed b/tests/ui/collapsible_if.fixed index e8f90b3164a9..076771f5c57e 100644 --- a/tests/ui/collapsible_if.fixed +++ b/tests/ui/collapsible_if.fixed @@ -7,28 +7,28 @@ fn main() { let x = "hello"; let y = "world"; if x == "hello" && y == "world" { - println!("Hello world!"); -} + println!("Hello world!"); + } if (x == "hello" || x == "world") && (y == "world" || y == "hello") { - println!("Hello world!"); -} + println!("Hello world!"); + } if x == "hello" && x == "world" && (y == "world" || y == "hello") { - println!("Hello world!"); -} + println!("Hello world!"); + } if (x == "hello" || x == "world") && y == "world" && y == "hello" { - println!("Hello world!"); -} + println!("Hello world!"); + } if x == "hello" && x == "world" && y == "world" && y == "hello" { - println!("Hello world!"); -} + println!("Hello world!"); + } if 42 == 1337 && 'a' != 'A' { - println!("world!") -} + println!("world!") + } // Works because any if with an else statement cannot be collapsed. if x == "hello" { @@ -81,8 +81,8 @@ fn main() { } if x == "hello" && y == "world" { // Collapsible - println!("Hello world!"); -} + println!("Hello world!"); + } if x == "hello" { print!("Hello "); diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index b123bc1c7bd7..6440ff41be81 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -12,8 +12,8 @@ LL | | } help: try | LL | if x == "hello" && y == "world" { -LL | println!("Hello world!"); -LL | } +LL | println!("Hello world!"); +LL | } | error: this `if` statement can be collapsed @@ -29,8 +29,8 @@ LL | | } help: try | LL | if (x == "hello" || x == "world") && (y == "world" || y == "hello") { -LL | println!("Hello world!"); -LL | } +LL | println!("Hello world!"); +LL | } | error: this `if` statement can be collapsed @@ -46,8 +46,8 @@ LL | | } help: try | LL | if x == "hello" && x == "world" && (y == "world" || y == "hello") { -LL | println!("Hello world!"); -LL | } +LL | println!("Hello world!"); +LL | } | error: this `if` statement can be collapsed @@ -63,8 +63,8 @@ LL | | } help: try | LL | if (x == "hello" || x == "world") && y == "world" && y == "hello" { -LL | println!("Hello world!"); -LL | } +LL | println!("Hello world!"); +LL | } | error: this `if` statement can be collapsed @@ -80,8 +80,8 @@ LL | | } help: try | LL | if x == "hello" && x == "world" && y == "world" && y == "hello" { -LL | println!("Hello world!"); -LL | } +LL | println!("Hello world!"); +LL | } | error: this `if` statement can be collapsed @@ -97,8 +97,8 @@ LL | | } help: try | LL | if 42 == 1337 && 'a' != 'A' { -LL | println!("world!") -LL | } +LL | println!("world!") +LL | } | error: this `if` statement can be collapsed @@ -114,8 +114,8 @@ LL | | } help: try | LL | if x == "hello" && y == "world" { // Collapsible -LL | println!("Hello world!"); -LL | } +LL | println!("Hello world!"); +LL | } | error: aborting due to 7 previous errors diff --git a/tests/ui/match_bool.stderr b/tests/ui/match_bool.stderr index 42f20862939b..d0c20eb2696b 100644 --- a/tests/ui/match_bool.stderr +++ b/tests/ui/match_bool.stderr @@ -40,8 +40,8 @@ LL | | }; help: consider using an `if`/`else` expression | LL | if !test { -LL | println!("Noooo!"); -LL | }; +LL | println!("Noooo!"); +LL | }; | error: you seem to be trying to match on a boolean expression @@ -58,8 +58,8 @@ LL | | }; help: consider using an `if`/`else` expression | LL | if !test { -LL | println!("Noooo!"); -LL | }; +LL | println!("Noooo!"); +LL | }; | error: you seem to be trying to match on a boolean expression @@ -76,8 +76,8 @@ LL | | }; help: consider using an `if`/`else` expression | LL | if !(test && test) { -LL | println!("Noooo!"); -LL | }; +LL | println!("Noooo!"); +LL | }; | error: equal expressions as operands to `&&` @@ -103,10 +103,10 @@ LL | | }; help: consider using an `if`/`else` expression | LL | if test { -LL | println!("Yes!"); -LL | } else { -LL | println!("Noooo!"); -LL | }; +LL | println!("Yes!"); +LL | } else { +LL | println!("Noooo!"); +LL | }; | error: aborting due to 8 previous errors diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr index 80ddeabdb2fd..f69554d75f9b 100644 --- a/tests/ui/single_match.stderr +++ b/tests/ui/single_match.stderr @@ -13,8 +13,8 @@ LL | | }; help: try this | LL | if let Some(y) = x { -LL | println!("{:?}", y); -LL | }; +LL | println!("{:?}", y); +LL | }; | error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let` diff --git a/tests/ui/single_match_else.stderr b/tests/ui/single_match_else.stderr index 3f29f5aaf6a3..59861d46eb34 100644 --- a/tests/ui/single_match_else.stderr +++ b/tests/ui/single_match_else.stderr @@ -14,9 +14,9 @@ LL | | } help: try this | LL | if let ExprNode::ExprAddrOf = ExprNode::Butterflies { Some(&NODE) } else { -LL | let x = 5; -LL | None -LL | } +LL | let x = 5; +LL | None +LL | } | error: aborting due to previous error From 250c1842b1e27c1eb6d174e8a954ea37a2f707bb Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 4 Feb 2020 17:02:46 +0100 Subject: [PATCH 013/243] Document the indent_relative_to arg of snippet_block --- clippy_lints/src/utils/mod.rs | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index b9a62382aa39..ed6d9f81cc9f 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -534,16 +534,40 @@ pub fn snippet_opt(cx: &T, span: Span) -> Option { cx.sess().source_map().span_to_snippet(span).ok() } -/// Converts a span (from a block) to a code snippet if available, otherwise use -/// default. -/// This trims the code of indentation, except for the first line. Use it for -/// blocks or block-like +/// Converts a span (from a block) to a code snippet if available, otherwise use default. +/// +/// This trims the code of indentation, except for the first line. Use it for blocks or block-like /// things which need to be printed as such. /// +/// The `indent_relative_to` arg can be used, to provide a span, where the indentation of the +/// resulting snippet of the given span. +/// /// # Example +/// /// ```rust,ignore -/// snippet_block(cx, expr.span, "..", None) +/// snippet_block(cx, block.span, "..", None) +/// // where, `block` is the block of the if expr +/// if x { +/// y; +/// } +/// // will return the snippet +/// { +/// y; +/// } +/// ``` +/// +/// ```rust,ignore +/// snippet_block(cx, block.span, "..", Some(if_expr.span)) +/// // where, `block` is the block of the if expr +/// if x { +/// y; +/// } +/// // will return the snippet +/// { +/// y; +/// } // aligned with `if` /// ``` +/// Note that the first line of the snippet always has 0 indentation. pub fn snippet_block<'a, T: LintContext>( cx: &T, span: Span, From c7979d35151b07809393a0d05b401222126916d5 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 5 Feb 2020 09:55:48 +0100 Subject: [PATCH 014/243] Fix rebase fallout --- clippy_lints/src/matches.rs | 13 ++++++------ tests/ui/match_single_binding.fixed | 30 ++++++++++++++-------------- tests/ui/match_single_binding.stderr | 30 ++++++++++++++-------------- 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 054535353470..d753b664045d 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -3,9 +3,9 @@ use crate::utils::paths; use crate::utils::sugg::Sugg; use crate::utils::usage::is_unused; use crate::utils::{ - expr_block, get_arg_name, in_macro, is_allowed, is_expn_of, is_refutable, is_wild, match_qpath, match_type, - match_var, multispan_sugg, remove_blocks, snippet, snippet_block, snippet_with_applicability, span_lint_and_help, - span_lint_and_note, span_lint_and_sugg, span_lint_and_then, walk_ptrs_ty, + expr_block, get_arg_name, in_macro, indent_of, is_allowed, is_expn_of, is_refutable, is_wild, match_qpath, + match_type, match_var, multispan_sugg, remove_blocks, snippet, snippet_block, snippet_with_applicability, + span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then, walk_ptrs_ty, }; use if_chain::if_chain; use rustc::lint::in_external_macro; @@ -836,7 +836,7 @@ fn check_match_single_binding(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[A let mut snippet_body = if match_body.span.from_expansion() { Sugg::hir_with_macro_callsite(cx, match_body, "..").to_string() } else { - snippet_block(cx, match_body.span, "..").to_owned().to_string() + snippet_block(cx, match_body.span, "..", Some(expr.span)).to_string() }; // Do we need to add ';' to suggestion ? @@ -865,10 +865,11 @@ fn check_match_single_binding(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[A "this match could be written as a `let` statement", "consider using `let` statement", format!( - "let {} = {};\n{}", + "let {} = {};\n{}{}", snippet_with_applicability(cx, bind_names, "..", &mut applicability), snippet_with_applicability(cx, matched_vars, "..", &mut applicability), - snippet_body + " ".repeat(indent_of(cx, expr.span).unwrap_or(0)), + snippet_body, ), applicability, ); diff --git a/tests/ui/match_single_binding.fixed b/tests/ui/match_single_binding.fixed index 8fb8dc323e43..932bd6783a15 100644 --- a/tests/ui/match_single_binding.fixed +++ b/tests/ui/match_single_binding.fixed @@ -14,12 +14,12 @@ fn main() { let c = 3; // Lint let (x, y, z) = (a, b, c); -{ - println!("{} {} {}", x, y, z); -} + { + println!("{} {} {}", x, y, z); + } // Lint let (x, y, z) = (a, b, c); -println!("{} {} {}", x, y, z); + println!("{} {} {}", x, y, z); // Ok match a { 2 => println!("2"), @@ -35,29 +35,29 @@ println!("{} {} {}", x, y, z); println!("whatever"); // Lint { - let x = 29; - println!("x has a value of {}", x); -} + let x = 29; + println!("x has a value of {}", x); + } // Lint { - let e = 5 * a; - if e >= 5 { - println!("e is superior to 5"); + let e = 5 * a; + if e >= 5 { + println!("e is superior to 5"); + } } -} // Lint let p = Point { x: 0, y: 7 }; let Point { x, y } = p; -println!("Coords: ({}, {})", x, y); + println!("Coords: ({}, {})", x, y); // Lint let Point { x: x1, y: y1 } = p; -println!("Coords: ({}, {})", x1, y1); + println!("Coords: ({}, {})", x1, y1); // Lint let x = 5; let ref r = x; -println!("Got a reference to {}", r); + println!("Got a reference to {}", r); // Lint let mut x = 5; let ref mut mr = x; -println!("Got a mutable reference to {}", mr); + println!("Got a mutable reference to {}", mr); } diff --git a/tests/ui/match_single_binding.stderr b/tests/ui/match_single_binding.stderr index d76e229adff0..471aec780d23 100644 --- a/tests/ui/match_single_binding.stderr +++ b/tests/ui/match_single_binding.stderr @@ -12,9 +12,9 @@ LL | | } help: consider using `let` statement | LL | let (x, y, z) = (a, b, c); -LL | { -LL | println!("{} {} {}", x, y, z); -LL | } +LL | { +LL | println!("{} {} {}", x, y, z); +LL | } | error: this match could be written as a `let` statement @@ -28,7 +28,7 @@ LL | | } help: consider using `let` statement | LL | let (x, y, z) = (a, b, c); -LL | println!("{} {} {}", x, y, z); +LL | println!("{} {} {}", x, y, z); | error: this match could be replaced by its body itself @@ -53,9 +53,9 @@ LL | | } help: consider using the match body instead | LL | { -LL | let x = 29; -LL | println!("x has a value of {}", x); -LL | } +LL | let x = 29; +LL | println!("x has a value of {}", x); +LL | } | error: this match could be replaced by its body itself @@ -73,11 +73,11 @@ LL | | } help: consider using the match body instead | LL | { -LL | let e = 5 * a; -LL | if e >= 5 { -LL | println!("e is superior to 5"); +LL | let e = 5 * a; +LL | if e >= 5 { +LL | println!("e is superior to 5"); +LL | } LL | } -LL | } | error: this match could be written as a `let` statement @@ -91,7 +91,7 @@ LL | | } help: consider using `let` statement | LL | let Point { x, y } = p; -LL | println!("Coords: ({}, {})", x, y); +LL | println!("Coords: ({}, {})", x, y); | error: this match could be written as a `let` statement @@ -105,7 +105,7 @@ LL | | } help: consider using `let` statement | LL | let Point { x: x1, y: y1 } = p; -LL | println!("Coords: ({}, {})", x1, y1); +LL | println!("Coords: ({}, {})", x1, y1); | error: this match could be written as a `let` statement @@ -119,7 +119,7 @@ LL | | } help: consider using `let` statement | LL | let ref r = x; -LL | println!("Got a reference to {}", r); +LL | println!("Got a reference to {}", r); | error: this match could be written as a `let` statement @@ -133,7 +133,7 @@ LL | | } help: consider using `let` statement | LL | let ref mut mr = x; -LL | println!("Got a mutable reference to {}", mr); +LL | println!("Got a mutable reference to {}", mr); | error: aborting due to 9 previous errors From 4068ff4d8a97cfdd21c717748e75a4839923e231 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 5 Feb 2020 10:42:33 +0100 Subject: [PATCH 015/243] Improve help message in needless_continue --- clippy_lints/src/needless_continue.rs | 26 ++++++++++++++------------ tests/ui/needless_continue.stderr | 6 ++++-- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 75cbfe13072e..45e5fdd5ce82 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -312,16 +312,16 @@ fn suggestion_snippet_for_continue_inside_if<'a>(ctx: &EarlyContext<'_>, data: & let cond_code = snippet(ctx, data.if_cond.span, ".."); let continue_code = snippet_block(ctx, data.if_block.span, "..", Some(data.if_expr.span)); - // region B + let else_code = snippet_block(ctx, data.else_expr.span, "..", Some(data.if_expr.span)); let indent_if = indent_of(ctx, data.if_expr.span).unwrap_or(0); format!( - "{}if {} {} {}", - " ".repeat(indent_if), + "{indent}if {} {}\n{indent}{}", cond_code, continue_code, else_code, + indent = " ".repeat(indent_if), ) } @@ -389,9 +389,9 @@ fn check_and_warn<'a>(ctx: &EarlyContext<'_>, expr: &'a ast::Expr) { }); } -/// Eats at `s` from the end till a closing brace `}` is encountered, and then -/// continues eating till a non-whitespace character is found. -/// e.g., the string +/// Eats at `s` from the end till a closing brace `}` is encountered, and then continues eating +/// till a non-whitespace character is found. e.g., the string. If no closing `}` is present, the +/// string will be preserved. /// /// ```rust /// { @@ -405,12 +405,9 @@ fn check_and_warn<'a>(ctx: &EarlyContext<'_>, expr: &'a ast::Expr) { /// { /// let x = 5; /// ``` -/// -/// NOTE: when there is no closing brace in `s`, `s` is _not_ preserved, i.e., -/// an empty string will be returned in that case. #[must_use] fn erode_from_back(s: &str) -> String { - let mut ret = String::from(s); + let mut ret = s.to_string(); while ret.pop().map_or(false, |c| c != '}') {} while let Some(c) = ret.pop() { if !c.is_whitespace() { @@ -418,7 +415,11 @@ fn erode_from_back(s: &str) -> String { break; } } - ret + if ret.is_empty() { + s.to_string() + } else { + ret + } } fn span_of_first_expr_in_block(block: &ast::Block) -> Option { @@ -428,6 +429,7 @@ fn span_of_first_expr_in_block(block: &ast::Block) -> Option { #[cfg(test)] mod test { use super::erode_from_back; + #[test] #[rustfmt::skip] fn test_erode_from_back() { @@ -453,7 +455,7 @@ mod test { let x = 5; let y = something(); "; - let expected = ""; + let expected = input; let got = erode_from_back(input); assert_eq!(expected, got); } diff --git a/tests/ui/needless_continue.stderr b/tests/ui/needless_continue.stderr index 6c4aa7445203..8d6a37df9601 100644 --- a/tests/ui/needless_continue.stderr +++ b/tests/ui/needless_continue.stderr @@ -48,7 +48,8 @@ LL | | } = help: consider dropping the `else` clause if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 { continue; - } { + } + { println!("Blabber"); println!("Jabber"); } @@ -89,7 +90,8 @@ LL | | } = help: consider dropping the `else` clause if condition() { continue; // should lint here - } { + } + { println!("bar-5"); } From e23881e1310f7fe02aeeecf3510a80cbac5aa808 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 5 Feb 2020 11:09:48 +0100 Subject: [PATCH 016/243] Rename ctx->cx in needless_continue --- clippy_lints/src/needless_continue.rs | 40 +++++++++++++-------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 45e5fdd5ce82..660aae25f557 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -119,9 +119,9 @@ declare_clippy_lint! { declare_lint_pass!(NeedlessContinue => [NEEDLESS_CONTINUE]); impl EarlyLintPass for NeedlessContinue { - fn check_expr(&mut self, ctx: &EarlyContext<'_>, expr: &ast::Expr) { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { if !expr.span.from_expansion() { - check_and_warn(ctx, expr); + check_and_warn(cx, expr); } } } @@ -283,24 +283,24 @@ const DROP_ELSE_BLOCK_AND_MERGE_MSG: &str = "consider dropping the `else` clause const DROP_ELSE_BLOCK_MSG: &str = "consider dropping the `else` clause"; -fn emit_warning<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str, typ: LintType) { +fn emit_warning<'a>(cx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str, typ: LintType) { // snip is the whole *help* message that appears after the warning. // message is the warning message. // expr is the expression which the lint warning message refers to. let (snip, message, expr) = match typ { LintType::ContinueInsideElseBlock => ( - suggestion_snippet_for_continue_inside_else(ctx, data), + suggestion_snippet_for_continue_inside_else(cx, data), MSG_REDUNDANT_ELSE_BLOCK, data.else_expr, ), LintType::ContinueInsideThenBlock => ( - suggestion_snippet_for_continue_inside_if(ctx, data), + suggestion_snippet_for_continue_inside_if(cx, data), MSG_ELSE_BLOCK_NOT_NEEDED, data.if_expr, ), }; span_lint_and_help( - ctx, + cx, NEEDLESS_CONTINUE, expr.span, message, @@ -308,14 +308,14 @@ fn emit_warning<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str ); } -fn suggestion_snippet_for_continue_inside_if<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>) -> String { - let cond_code = snippet(ctx, data.if_cond.span, ".."); +fn suggestion_snippet_for_continue_inside_if<'a>(cx: &EarlyContext<'_>, data: &'a LintData<'_>) -> String { + let cond_code = snippet(cx, data.if_cond.span, ".."); - let continue_code = snippet_block(ctx, data.if_block.span, "..", Some(data.if_expr.span)); + let continue_code = snippet_block(cx, data.if_block.span, "..", Some(data.if_expr.span)); - let else_code = snippet_block(ctx, data.else_expr.span, "..", Some(data.if_expr.span)); + let else_code = snippet_block(cx, data.else_expr.span, "..", Some(data.if_expr.span)); - let indent_if = indent_of(ctx, data.if_expr.span).unwrap_or(0); + let indent_if = indent_of(cx, data.if_expr.span).unwrap_or(0); format!( "{indent}if {} {}\n{indent}{}", cond_code, @@ -325,24 +325,24 @@ fn suggestion_snippet_for_continue_inside_if<'a>(ctx: &EarlyContext<'_>, data: & ) } -fn suggestion_snippet_for_continue_inside_else<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>) -> String { - let cond_code = snippet(ctx, data.if_cond.span, ".."); +fn suggestion_snippet_for_continue_inside_else<'a>(cx: &EarlyContext<'_>, data: &'a LintData<'_>) -> String { + let cond_code = snippet(cx, data.if_cond.span, ".."); // Region B - let block_code = erode_from_back(&snippet_block(ctx, data.if_block.span, "..", Some(data.if_expr.span))); + let block_code = erode_from_back(&snippet_block(cx, data.if_block.span, "..", Some(data.if_expr.span))); // Region C // These is the code in the loop block that follows the if/else construction // we are complaining about. We want to pull all of this code into the // `then` block of the `if` statement. let indent = span_of_first_expr_in_block(data.if_block) - .and_then(|span| indent_of(ctx, span)) + .and_then(|span| indent_of(cx, span)) .unwrap_or(0); let to_annex = data.block_stmts[data.stmt_idx + 1..] .iter() .map(|stmt| original_sp(stmt.span, DUMMY_SP)) .map(|span| { - let snip = snippet_block(ctx, span, "..", None).into_owned(); + let snip = snippet_block(cx, span, "..", None).into_owned(); snip.lines() .map(|line| format!("{}{}", " ".repeat(indent), line)) .collect::>() @@ -351,7 +351,7 @@ fn suggestion_snippet_for_continue_inside_else<'a>(ctx: &EarlyContext<'_>, data: .collect::>() .join("\n"); - let indent_if = indent_of(ctx, data.if_expr.span).unwrap_or(0); + let indent_if = indent_of(cx, data.if_expr.span).unwrap_or(0); format!( "{indent_if}if {} {}\n{indent}// merged code follows:\n{}\n{indent_if}}}", cond_code, @@ -362,7 +362,7 @@ fn suggestion_snippet_for_continue_inside_else<'a>(ctx: &EarlyContext<'_>, data: ) } -fn check_and_warn<'a>(ctx: &EarlyContext<'_>, expr: &'a ast::Expr) { +fn check_and_warn<'a>(cx: &EarlyContext<'_>, expr: &'a ast::Expr) { with_loop_block(expr, |loop_block, label| { for (i, stmt) in loop_block.stmts.iter().enumerate() { with_if_expr(stmt, |if_expr, cond, then_block, else_expr| { @@ -376,13 +376,13 @@ fn check_and_warn<'a>(ctx: &EarlyContext<'_>, expr: &'a ast::Expr) { }; if needless_continue_in_else(else_expr, label) { emit_warning( - ctx, + cx, data, DROP_ELSE_BLOCK_AND_MERGE_MSG, LintType::ContinueInsideElseBlock, ); } else if is_first_block_stmt_continue(then_block, label) { - emit_warning(ctx, data, DROP_ELSE_BLOCK_MSG, LintType::ContinueInsideThenBlock); + emit_warning(cx, data, DROP_ELSE_BLOCK_MSG, LintType::ContinueInsideThenBlock); } }); } From 9897927504ca64b90e2e7a742a22d7ddb6a3bc69 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 6 Feb 2020 20:29:58 +0100 Subject: [PATCH 017/243] Rustup to rust-lang/rust#68788 --- clippy_lints/src/misc_early.rs | 4 ++-- clippy_lints/src/non_expressive_names.rs | 2 +- clippy_lints/src/returns.rs | 9 +++++---- clippy_lints/src/utils/internal_lints.rs | 8 +++----- tests/ui/custom_ice_message.stderr | 2 +- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 6f54750cb9b9..e0e2a0caee4e 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -372,10 +372,10 @@ impl EarlyLintPass for MiscEarlyLints { check_unneeded_wildcard_pattern(cx, pat); } - fn check_fn(&mut self, cx: &EarlyContext<'_>, _: FnKind<'_>, decl: &FnDecl, _: Span, _: NodeId) { + fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, _: Span, _: NodeId) { let mut registered_names: FxHashMap = FxHashMap::default(); - for arg in &decl.inputs { + for arg in &fn_kind.decl().inputs { if let PatKind::Ident(_, ident, None) = arg.pat.kind { let arg_name = ident.to_string(); diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index b9df82d65e3b..2a7fbe6c0c64 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -352,7 +352,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> { impl EarlyLintPass for NonExpressiveNames { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if let ItemKind::Fn(ref sig, _, ref blk) = item.kind { + if let ItemKind::Fn(ref sig, _, Some(ref blk)) = item.kind { do_check(self, cx, &item.attrs, &sig.decl, blk); } } diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index c903df0f2119..6bf373a9a626 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -235,13 +235,14 @@ impl Return { } impl EarlyLintPass for Return { - fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, decl: &ast::FnDecl, span: Span, _: ast::NodeId) { + fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, span: Span, _: ast::NodeId) { match kind { - FnKind::ItemFn(.., block) | FnKind::Method(.., block) => self.check_block_return(cx, block), - FnKind::Closure(body) => self.check_final_expr(cx, body, Some(body.span), RetReplacement::Empty), + FnKind::Fn(.., Some(block)) => self.check_block_return(cx, block), + FnKind::Closure(_, body) => self.check_final_expr(cx, body, Some(body.span), RetReplacement::Empty), + FnKind::Fn(.., None) => {}, } if_chain! { - if let ast::FunctionRetTy::Ty(ref ty) = decl.output; + if let ast::FunctionRetTy::Ty(ref ty) = kind.decl().output; if let ast::TyKind::Tup(ref vals) = ty.kind; if vals.is_empty() && !ty.span.from_expansion() && get_def(span) == get_def(ty.span); then { diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index af07cf666583..945999de89fe 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -380,18 +380,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OuterExpnDataPass { declare_lint_pass!(ProduceIce => [PRODUCE_ICE]); impl EarlyLintPass for ProduceIce { - fn check_fn(&mut self, _: &EarlyContext<'_>, fn_kind: FnKind<'_>, _: &ast::FnDecl, _: Span, _: ast::NodeId) { + fn check_fn(&mut self, _: &EarlyContext<'_>, fn_kind: FnKind<'_>, _: Span, _: ast::NodeId) { if is_trigger_fn(fn_kind) { - panic!("Testing the ICE message"); + panic!("Would you like some help with that?"); } } } fn is_trigger_fn(fn_kind: FnKind<'_>) -> bool { match fn_kind { - FnKind::ItemFn(ident, ..) | FnKind::Method(ident, ..) => { - ident.name.as_str() == "it_looks_like_you_are_trying_to_kill_clippy" - }, + FnKind::Fn(_, ident, ..) => ident.name.as_str() == "it_looks_like_you_are_trying_to_kill_clippy", FnKind::Closure(..) => false, } } diff --git a/tests/ui/custom_ice_message.stderr b/tests/ui/custom_ice_message.stderr index 36f243ebc5fb..a9a65a38c109 100644 --- a/tests/ui/custom_ice_message.stderr +++ b/tests/ui/custom_ice_message.stderr @@ -1,4 +1,4 @@ -thread 'rustc' panicked at 'Testing the ICE message', clippy_lints/src/utils/internal_lints.rs +thread 'rustc' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints.rs note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace error: internal compiler error: unexpected panic From 5fa33e8b7abd31dcad805abaaf84990465975723 Mon Sep 17 00:00:00 2001 From: mgr-inz-rafal Date: Thu, 6 Feb 2020 20:36:54 +0100 Subject: [PATCH 018/243] Add issue4983() to test --- clippy_lints/src/needless_bool.rs | 6 +++--- tests/ui/bool_comparison.stderr | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index d0b89158f359..4c9aacee6db5 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -2,9 +2,9 @@ //! //! This lint is **warn** by default -use if_chain::if_chain; use crate::utils::sugg::Sugg; use crate::utils::{higher, parent_node_is_if_expr, span_lint, span_lint_and_help, span_lint_and_sugg}; +use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::*; use rustc_lint::{LateContext, LateLintPass}; @@ -192,7 +192,7 @@ fn is_unary_not<'tcx>(e: &'tcx Expr<'_>) -> bool { } }; false - } +} fn one_side_is_unary_not<'tcx>(left_side: &'tcx Expr<'_>, right_side: &'tcx Expr<'_>) -> bool { is_unary_not(left_side) ^ is_unary_not(right_side) @@ -216,7 +216,7 @@ fn check_comparison<'a, 'tcx>( if let BinOpKind::Eq = op.node; if one_side_is_unary_not(&left_side, &right_side); then { - span_lint_and_help(cx, BOOL_COMPARISON, e.span, "help1", "help2"); + span_lint_and_help(cx, BOOL_COMPARISON, e.span, "Here comes", "the suggestion"); } }; diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index 2aa070a00f30..cec7b196a23f 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -84,5 +84,21 @@ error: order comparisons between booleans can be simplified LL | if x > y { | ^^^^^ help: try simplifying it as shown: `x & !y` -error: aborting due to 14 previous errors +error: Here comes + --> $DIR/bool_comparison.rs:119:8 + | +LL | if a == !b {}; + | ^^^^^^^ + | + = help: the suggestion + +error: Here comes + --> $DIR/bool_comparison.rs:120:8 + | +LL | if !a == b {}; + | ^^^^^^^ + | + = help: the suggestion + +error: aborting due to 16 previous errors From 729f943c53586013c7306e0485565fd089964fa3 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 6 Feb 2020 21:13:39 +0700 Subject: [PATCH 019/243] dev: Prefer `fs::read*` and improvement to replace text region --- clippy_dev/src/lib.rs | 54 ++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index c58b80e4318e..f50ef4aff950 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -6,7 +6,6 @@ use regex::Regex; use std::collections::HashMap; use std::ffi::OsStr; use std::fs; -use std::io::prelude::*; use std::path::{Path, PathBuf}; use walkdir::WalkDir; @@ -172,9 +171,7 @@ pub fn gather_all() -> impl Iterator { } fn gather_from_file(dir_entry: &walkdir::DirEntry) -> impl Iterator { - let mut file = fs::File::open(dir_entry.path()).unwrap(); - let mut content = String::new(); - file.read_to_string(&mut content).unwrap(); + let content = fs::read_to_string(dir_entry.path()).unwrap(); let mut filename = dir_entry.path().file_stem().unwrap().to_str().unwrap(); // If the lints are stored in mod.rs, we get the module name from // the containing directory: @@ -209,7 +206,7 @@ fn lint_files() -> impl Iterator { let path = clippy_project_root().join("clippy_lints/src"); WalkDir::new(path) .into_iter() - .filter_map(std::result::Result::ok) + .filter_map(Result::ok) .filter(|f| f.path().extension() == Some(OsStr::new("rs"))) } @@ -225,7 +222,6 @@ pub struct FileChange { /// `path` is the relative path to the file on which you want to perform the replacement. /// /// See `replace_region_in_text` for documentation of the other options. -#[allow(clippy::expect_fun_call)] pub fn replace_region_in_file( path: &Path, start: &str, @@ -235,22 +231,15 @@ pub fn replace_region_in_file( replacements: F, ) -> FileChange where - F: Fn() -> Vec, + F: FnOnce() -> Vec, { - let path = clippy_project_root().join(path); - let mut f = fs::File::open(&path).expect(&format!("File not found: {}", path.to_string_lossy())); - let mut contents = String::new(); - f.read_to_string(&mut contents) - .expect("Something went wrong reading the file"); + let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from {}: {}", path.display(), e)); let file_change = replace_region_in_text(&contents, start, end, replace_start, replacements); if write_back { - let mut f = fs::File::create(&path).expect(&format!("File not found: {}", path.to_string_lossy())); - f.write_all(file_change.new_lines.as_bytes()) - .expect("Unable to write file"); - // Ensure we write the changes with a trailing newline so that - // the file has the proper line endings. - f.write_all(b"\n").expect("Unable to write file"); + if let Err(e) = fs::write(path, file_change.new_lines.as_bytes()) { + panic!("Cannot write to {}: {}", path.display(), e); + } } file_change } @@ -273,31 +262,32 @@ where /// /// ``` /// let the_text = "replace_start\nsome text\nthat will be replaced\nreplace_end"; -/// let result = clippy_dev::replace_region_in_text(the_text, r#"replace_start"#, r#"replace_end"#, false, || { -/// vec!["a different".to_string(), "text".to_string()] -/// }) -/// .new_lines; +/// let result = +/// clippy_dev::replace_region_in_text(the_text, "replace_start", "replace_end", false, || { +/// vec!["a different".to_string(), "text".to_string()] +/// }) +/// .new_lines; /// assert_eq!("replace_start\na different\ntext\nreplace_end", result); /// ``` pub fn replace_region_in_text(text: &str, start: &str, end: &str, replace_start: bool, replacements: F) -> FileChange where - F: Fn() -> Vec, + F: FnOnce() -> Vec, { - let lines = text.lines(); + let replace_it = replacements(); let mut in_old_region = false; let mut found = false; let mut new_lines = vec![]; let start = Regex::new(start).unwrap(); let end = Regex::new(end).unwrap(); - for line in lines.clone() { + for line in text.lines() { if in_old_region { - if end.is_match(&line) { + if end.is_match(line) { in_old_region = false; - new_lines.extend(replacements()); + new_lines.extend(replace_it.clone()); new_lines.push(line.to_string()); } - } else if start.is_match(&line) { + } else if start.is_match(line) { if !replace_start { new_lines.push(line.to_string()); } @@ -315,10 +305,12 @@ where eprintln!("error: regex `{:?}` not found. You may have to update it.", start); } - FileChange { - changed: lines.ne(new_lines.clone()), - new_lines: new_lines.join("\n"), + let mut new_lines = new_lines.join("\n"); + if text.ends_with('\n') { + new_lines.push('\n'); } + let changed = new_lines != text; + FileChange { changed, new_lines } } /// Returns the path to the Clippy project directory From 344603afcef264bc1790bca6865dbfb4815d2d5d Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 6 Feb 2020 21:28:50 +0700 Subject: [PATCH 020/243] dev: Make UpdateMode a copy type --- clippy_dev/src/main.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 7369db1f078d..403aa634c34f 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -8,7 +8,7 @@ mod fmt; mod new_lint; mod stderr_length_check; -#[derive(PartialEq)] +#[derive(Clone, Copy, PartialEq)] enum UpdateMode { Check, Change, @@ -113,9 +113,9 @@ fn main() { if matches.is_present("print-only") { print_lints(); } else if matches.is_present("check") { - update_lints(&UpdateMode::Check); + update_lints(UpdateMode::Check); } else { - update_lints(&UpdateMode::Change); + update_lints(UpdateMode::Change); } }, ("new_lint", Some(matches)) => { @@ -124,7 +124,7 @@ fn main() { matches.value_of("name"), matches.value_of("category"), ) { - Ok(_) => update_lints(&UpdateMode::Change), + Ok(_) => update_lints(UpdateMode::Change), Err(e) => eprintln!("Unable to create lint: {}", e), } }, @@ -161,7 +161,7 @@ fn print_lints() { } #[allow(clippy::too_many_lines)] -fn update_lints(update_mode: &UpdateMode) { +fn update_lints(update_mode: UpdateMode) { let lint_list: Vec = gather_all().collect(); let usable_lints: Vec = Lint::usable_lints(lint_list.clone().into_iter()).collect(); @@ -175,7 +175,7 @@ fn update_lints(update_mode: &UpdateMode) { "begin lint list", "end lint list", false, - update_mode == &UpdateMode::Change, + update_mode == UpdateMode::Change, || { format!( "pub const ALL_LINTS: [Lint; {}] = {:#?};", @@ -194,7 +194,7 @@ fn update_lints(update_mode: &UpdateMode) { r#"\[There are \d+ lints included in this crate!\]\(https://rust-lang.github.io/rust-clippy/master/index.html\)"#, "", true, - update_mode == &UpdateMode::Change, + update_mode == UpdateMode::Change, || { vec![ format!("[There are {} lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)", lint_count) @@ -207,7 +207,7 @@ fn update_lints(update_mode: &UpdateMode) { "", "", false, - update_mode == &UpdateMode::Change, + update_mode == UpdateMode::Change, || gen_changelog_lint_list(lint_list.clone()), ) .changed; @@ -217,7 +217,7 @@ fn update_lints(update_mode: &UpdateMode) { "begin deprecated lints", "end deprecated lints", false, - update_mode == &UpdateMode::Change, + update_mode == UpdateMode::Change, || gen_deprecated(&lint_list), ) .changed; @@ -227,7 +227,7 @@ fn update_lints(update_mode: &UpdateMode) { "begin register lints", "end register lints", false, - update_mode == &UpdateMode::Change, + update_mode == UpdateMode::Change, || gen_register_lint_list(&lint_list), ) .changed; @@ -237,7 +237,7 @@ fn update_lints(update_mode: &UpdateMode) { "begin lints modules", "end lints modules", false, - update_mode == &UpdateMode::Change, + update_mode == UpdateMode::Change, || gen_modules_list(lint_list.clone()), ) .changed; @@ -248,7 +248,7 @@ fn update_lints(update_mode: &UpdateMode) { r#"store.register_group\(true, "clippy::all""#, r#"\]\);"#, false, - update_mode == &UpdateMode::Change, + update_mode == UpdateMode::Change, || { // clippy::all should only include the following lint groups: let all_group_lints = usable_lints @@ -271,13 +271,13 @@ fn update_lints(update_mode: &UpdateMode) { &format!("store.register_group\\(true, \"clippy::{}\"", lint_group), r#"\]\);"#, false, - update_mode == &UpdateMode::Change, + update_mode == UpdateMode::Change, || gen_lint_group_list(lints.clone()), ) .changed; } - if update_mode == &UpdateMode::Check && file_change { + if update_mode == UpdateMode::Check && file_change { println!( "Not all lints defined properly. \ Please run `cargo dev update_lints` to make sure all lints are defined properly." From cf58537bd672807f8aa2b65be0ad88fd5a77b4f2 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Fri, 7 Feb 2020 08:33:01 +0700 Subject: [PATCH 021/243] dev: Move DOCS_LINK out of lazy_static and reuse it --- clippy_dev/src/lib.rs | 5 +++-- clippy_dev/src/main.rs | 16 +++++++++------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index f50ef4aff950..3acecf967910 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -30,9 +30,10 @@ lazy_static! { ) .unwrap(); static ref NL_ESCAPE_RE: Regex = Regex::new(r#"\\\n\s*"#).unwrap(); - pub static ref DOCS_LINK: String = "https://rust-lang.github.io/rust-clippy/master/index.html".to_string(); } +pub static DOCS_LINK: &str = "https://rust-lang.github.io/rust-clippy/master/index.html"; + /// Lint data parsed from the Clippy source code. #[derive(Clone, PartialEq, Debug)] pub struct Lint { @@ -120,7 +121,7 @@ pub fn gen_changelog_lint_list(lints: Vec) -> Vec { if l.is_internal() { None } else { - Some(format!("[`{}`]: {}#{}", l.name, DOCS_LINK.clone(), l.name)) + Some(format!("[`{}`]: {}#{}", l.name, DOCS_LINK, l.name)) } }) .collect() diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 403aa634c34f..154876817429 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -150,7 +150,7 @@ fn print_lints() { println!( "* [{}]({}#{}) ({})", lint.name, - clippy_dev::DOCS_LINK.clone(), + clippy_dev::DOCS_LINK, lint.name, lint.desc ); @@ -191,16 +191,18 @@ fn update_lints(update_mode: UpdateMode) { file_change |= replace_region_in_file( Path::new("README.md"), - r#"\[There are \d+ lints included in this crate!\]\(https://rust-lang.github.io/rust-clippy/master/index.html\)"#, + &format!(r#"\[There are \d+ lints included in this crate!\]\({}\)"#, DOCS_LINK), "", true, update_mode == UpdateMode::Change, || { - vec![ - format!("[There are {} lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)", lint_count) - ] - } - ).changed; + vec![format!( + "[There are {} lints included in this crate!]({})", + lint_count, DOCS_LINK + )] + }, + ) + .changed; file_change |= replace_region_in_file( Path::new("CHANGELOG.md"), From c6a4beaf5626e47a286a229d78adf6df19016ac7 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Fri, 7 Feb 2020 04:34:06 +0100 Subject: [PATCH 022/243] Rustup https://github.com/rust-lang/rust/pull/67359 --- tests/ui/assertions_on_constants.stderr | 10 +++++++++- tests/ui/checked_unwrap/simple_conditionals.stderr | 2 ++ tests/ui/crashes/ice-2636.stderr | 1 + tests/ui/declare_interior_mutable_const.stderr | 4 ++++ tests/ui/default_lint.stderr | 2 +- tests/ui/derive_hash_xor_eq.stderr | 4 ++++ tests/ui/doc_unsafe.stderr | 2 ++ tests/ui/fallible_impl_from.stderr | 6 +++--- tests/ui/implicit_hasher.stderr | 3 +++ tests/ui/lint_without_lint_pass.stderr | 2 +- tests/ui/match_same_arms2.stderr | 4 ++-- tests/ui/mem_discriminant.stderr | 2 ++ tests/ui/mem_replace_macro.stderr | 1 + tests/ui/mut_mut.stderr | 2 ++ tests/ui/unit_cmp.stderr | 8 ++++---- tests/ui/unseparated_prefix_literals.stderr | 2 ++ tests/ui/use_self.stderr | 4 ++++ 17 files changed, 47 insertions(+), 12 deletions(-) diff --git a/tests/ui/assertions_on_constants.stderr b/tests/ui/assertions_on_constants.stderr index 0ff0f51ce8c2..8f09c8ce9d52 100644 --- a/tests/ui/assertions_on_constants.stderr +++ b/tests/ui/assertions_on_constants.stderr @@ -6,6 +6,7 @@ LL | assert!(true); | = note: `-D clippy::assertions-on-constants` implied by `-D warnings` = help: remove it + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `assert!(false)` should probably be replaced --> $DIR/assertions_on_constants.rs:10:5 @@ -14,6 +15,7 @@ LL | assert!(false); | ^^^^^^^^^^^^^^^ | = help: use `panic!()` or `unreachable!()` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `assert!(true)` will be optimized out by the compiler --> $DIR/assertions_on_constants.rs:11:5 @@ -22,6 +24,7 @@ LL | assert!(true, "true message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: remove it + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `assert!(false, "false message")` should probably be replaced --> $DIR/assertions_on_constants.rs:12:5 @@ -30,6 +33,7 @@ LL | assert!(false, "false message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: use `panic!("false message")` or `unreachable!("false message")` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `assert!(false, msg.to_uppercase())` should probably be replaced --> $DIR/assertions_on_constants.rs:15:5 @@ -38,6 +42,7 @@ LL | assert!(false, msg.to_uppercase()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: use `panic!(msg.to_uppercase())` or `unreachable!(msg.to_uppercase())` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `assert!(true)` will be optimized out by the compiler --> $DIR/assertions_on_constants.rs:18:5 @@ -46,6 +51,7 @@ LL | assert!(B); | ^^^^^^^^^^^ | = help: remove it + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `assert!(false)` should probably be replaced --> $DIR/assertions_on_constants.rs:21:5 @@ -54,6 +60,7 @@ LL | assert!(C); | ^^^^^^^^^^^ | = help: use `panic!()` or `unreachable!()` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `assert!(false, "C message")` should probably be replaced --> $DIR/assertions_on_constants.rs:22:5 @@ -62,6 +69,7 @@ LL | assert!(C, "C message"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | = help: use `panic!("C message")` or `unreachable!("C message")` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `debug_assert!(true)` will be optimized out by the compiler --> $DIR/assertions_on_constants.rs:24:5 @@ -70,7 +78,7 @@ LL | debug_assert!(true); | ^^^^^^^^^^^^^^^^^^^^ | = help: remove it - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 9 previous errors diff --git a/tests/ui/checked_unwrap/simple_conditionals.stderr b/tests/ui/checked_unwrap/simple_conditionals.stderr index b226bd726403..e40542e2e4f9 100644 --- a/tests/ui/checked_unwrap/simple_conditionals.stderr +++ b/tests/ui/checked_unwrap/simple_conditionals.stderr @@ -54,6 +54,8 @@ LL | $a.unwrap(); // unnecessary ... LL | m!(x); | ------ in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. --> $DIR/simple_conditionals.rs:27:9 diff --git a/tests/ui/crashes/ice-2636.stderr b/tests/ui/crashes/ice-2636.stderr index aba8be4adcc1..53799b4fbf1d 100644 --- a/tests/ui/crashes/ice-2636.stderr +++ b/tests/ui/crashes/ice-2636.stderr @@ -11,6 +11,7 @@ LL | test_hash!(&a, A => 0, B => 1, C => 2); | --------------------------------------- in this macro invocation | = note: `-D clippy::match-ref-pats` implied by `-D warnings` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/tests/ui/declare_interior_mutable_const.stderr b/tests/ui/declare_interior_mutable_const.stderr index ca7831618eda..6a9a57361f9f 100644 --- a/tests/ui/declare_interior_mutable_const.stderr +++ b/tests/ui/declare_interior_mutable_const.stderr @@ -32,6 +32,8 @@ LL | const $name: $ty = $e; ... LL | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable | ------------------------------------------ in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: a `const` item should never be interior mutable --> $DIR/declare_interior_mutable_const.rs:40:5 @@ -71,6 +73,8 @@ LL | const $name: $ty = $e; ... LL | declare_const!(ANOTHER_INPUT: T = Self::INPUT); //~ ERROR interior mutable | ----------------------------------------------- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: a `const` item should never be interior mutable --> $DIR/declare_interior_mutable_const.rs:60:5 diff --git a/tests/ui/default_lint.stderr b/tests/ui/default_lint.stderr index a37759db24b2..fc76dec82223 100644 --- a/tests/ui/default_lint.stderr +++ b/tests/ui/default_lint.stderr @@ -15,7 +15,7 @@ note: the lint level is defined here LL | #![deny(clippy::internal)] | ^^^^^^^^^^^^^^^^ = note: `#[deny(clippy::default_lint)]` implied by `#[deny(clippy::internal)]` - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/tests/ui/derive_hash_xor_eq.stderr b/tests/ui/derive_hash_xor_eq.stderr index 10c38bb42e39..2287a548fe46 100644 --- a/tests/ui/derive_hash_xor_eq.stderr +++ b/tests/ui/derive_hash_xor_eq.stderr @@ -14,6 +14,7 @@ LL | | true LL | | } LL | | } | |_^ + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: you are deriving `Hash` but have implemented `PartialEq` explicitly --> $DIR/derive_hash_xor_eq.rs:19:10 @@ -30,6 +31,7 @@ LL | | true LL | | } LL | | } | |_^ + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: you are implementing `Hash` explicitly but have derived `PartialEq` --> $DIR/derive_hash_xor_eq.rs:31:1 @@ -44,6 +46,7 @@ note: `PartialEq` implemented here | LL | #[derive(PartialEq)] | ^^^^^^^^^ + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: you are implementing `Hash` explicitly but have derived `PartialEq` --> $DIR/derive_hash_xor_eq.rs:49:5 @@ -58,6 +61,7 @@ note: `PartialEq` implemented here | LL | #[derive(PartialEq)] | ^^^^^^^^^ + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/tests/ui/doc_unsafe.stderr b/tests/ui/doc_unsafe.stderr index 9c8666419ff0..c784d41ba172 100644 --- a/tests/ui/doc_unsafe.stderr +++ b/tests/ui/doc_unsafe.stderr @@ -40,6 +40,8 @@ LL | | } ... LL | very_unsafe!(); | --------------- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 5 previous errors diff --git a/tests/ui/fallible_impl_from.stderr b/tests/ui/fallible_impl_from.stderr index 4142f7ede116..ab976b947b35 100644 --- a/tests/ui/fallible_impl_from.stderr +++ b/tests/ui/fallible_impl_from.stderr @@ -38,7 +38,7 @@ note: potential failure(s) | LL | panic!(); | ^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: consider implementing `TryFrom` instead --> $DIR/fallible_impl_from.rs:35:1 @@ -65,7 +65,7 @@ LL | } else if s.parse::().unwrap() != 42 { | ^^^^^^^^^^^^^^^^^^^^^^^^^ LL | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: consider implementing `TryFrom` instead --> $DIR/fallible_impl_from.rs:53:1 @@ -87,7 +87,7 @@ LL | if s.parse::().ok().unwrap() != 42 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr index b73d9716adc7..252e9eb5dd8c 100644 --- a/tests/ui/implicit_hasher.stderr +++ b/tests/ui/implicit_hasher.stderr @@ -105,6 +105,7 @@ LL | impl Foo for HashMap { LL | gen!(impl); | ----------- in this macro invocation | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) help: consider adding a type parameter | LL | impl Foo for HashMap { @@ -123,6 +124,7 @@ LL | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) LL | gen!(fn bar); | ------------- in this macro invocation | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) help: consider adding a type parameter | LL | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} @@ -137,6 +139,7 @@ LL | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) LL | gen!(fn bar); | ------------- in this macro invocation | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) help: consider adding a type parameter | LL | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} diff --git a/tests/ui/lint_without_lint_pass.stderr b/tests/ui/lint_without_lint_pass.stderr index ee7593d1b95f..1257dae96d71 100644 --- a/tests/ui/lint_without_lint_pass.stderr +++ b/tests/ui/lint_without_lint_pass.stderr @@ -15,7 +15,7 @@ note: the lint level is defined here LL | #![deny(clippy::internal)] | ^^^^^^^^^^^^^^^^ = note: `#[deny(clippy::lint_without_lint_pass)]` implied by `#[deny(clippy::internal)]` - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/tests/ui/match_same_arms2.stderr b/tests/ui/match_same_arms2.stderr index 28abb2fc9bf2..26c65f32ad78 100644 --- a/tests/ui/match_same_arms2.stderr +++ b/tests/ui/match_same_arms2.stderr @@ -121,7 +121,7 @@ help: consider refactoring into `(Ok(x), Some(_)) | (Ok(_), Some(x))` | LL | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^ - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: this `match` has identical arm bodies --> $DIR/match_same_arms2.rs:117:18 @@ -139,7 +139,7 @@ help: consider refactoring into `Ok(3) | Ok(_)` | LL | Ok(3) => println!("ok"), | ^^^^^ - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 7 previous errors diff --git a/tests/ui/mem_discriminant.stderr b/tests/ui/mem_discriminant.stderr index 1dd6610d5a30..8d9810970ade 100644 --- a/tests/ui/mem_discriminant.stderr +++ b/tests/ui/mem_discriminant.stderr @@ -71,6 +71,8 @@ LL | mem_discriminant_but_in_a_macro!(&rro); | | | | | help: try dereferencing: `*rro` | in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: calling `mem::discriminant` on non-enum type `&&&&&std::option::Option` --> $DIR/mem_discriminant.rs:34:5 diff --git a/tests/ui/mem_replace_macro.stderr b/tests/ui/mem_replace_macro.stderr index a0872b1a6bf4..4971a91050bf 100644 --- a/tests/ui/mem_replace_macro.stderr +++ b/tests/ui/mem_replace_macro.stderr @@ -8,6 +8,7 @@ LL | take!(s); | --------- in this macro invocation | = note: `-D clippy::mem-replace-with-default` implied by `-D warnings` + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/tests/ui/mut_mut.stderr b/tests/ui/mut_mut.stderr index 6fa5dbfc29f3..44e814227141 100644 --- a/tests/ui/mut_mut.stderr +++ b/tests/ui/mut_mut.stderr @@ -20,6 +20,8 @@ LL | &mut $p ... LL | let mut z = mut_ptr!(&mut 3u32); | ------------------- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: this expression mutably borrows a mutable reference. Consider reborrowing --> $DIR/mut_mut.rs:22:21 diff --git a/tests/ui/unit_cmp.stderr b/tests/ui/unit_cmp.stderr index 578a6218ee03..c8c0a85dfc10 100644 --- a/tests/ui/unit_cmp.stderr +++ b/tests/ui/unit_cmp.stderr @@ -34,7 +34,7 @@ LL | | } LL | | ); | |______^ | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `debug_assert_eq` of unit values detected. This will always succeed --> $DIR/unit_cmp.rs:32:5 @@ -48,7 +48,7 @@ LL | | } LL | | ); | |______^ | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `assert_ne` of unit values detected. This will always fail --> $DIR/unit_cmp.rs:41:5 @@ -62,7 +62,7 @@ LL | | } LL | | ); | |______^ | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `debug_assert_ne` of unit values detected. This will always fail --> $DIR/unit_cmp.rs:49:5 @@ -76,7 +76,7 @@ LL | | } LL | | ); | |______^ | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 6 previous errors diff --git a/tests/ui/unseparated_prefix_literals.stderr b/tests/ui/unseparated_prefix_literals.stderr index d353d34fb357..d7dd526bcb9a 100644 --- a/tests/ui/unseparated_prefix_literals.stderr +++ b/tests/ui/unseparated_prefix_literals.stderr @@ -50,6 +50,8 @@ LL | 42usize ... LL | let _ = lit_from_macro!(); | ----------------- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: integer type suffix should be separated by an underscore --> $DIR/unseparated_prefix_literals.rs:40:16 diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 3cdb1cb32495..b33928597c14 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -56,6 +56,8 @@ LL | fn new() -> Foo { ... LL | use_self_expand!(); // Should lint in local macros | ------------------- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: unnecessary structure name repetition --> $DIR/use_self.rs:113:17 @@ -65,6 +67,8 @@ LL | Foo {} ... LL | use_self_expand!(); // Should lint in local macros | ------------------- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: unnecessary structure name repetition --> $DIR/use_self.rs:148:21 From 9a12baad35e193bcb70a97139f47f090f51f253d Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Fri, 7 Feb 2020 10:34:11 +0700 Subject: [PATCH 023/243] Update CARGO_TARGET_DIR --- tests/ui/update-all-references.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/ui/update-all-references.sh b/tests/ui/update-all-references.sh index 9f970ea26b71..30ba9188db43 100755 --- a/tests/ui/update-all-references.sh +++ b/tests/ui/update-all-references.sh @@ -12,7 +12,10 @@ if [[ "$1" == "--help" || "$1" == "-h" ]]; then echo "usage: $0" fi -BUILD_DIR=$PWD/target/debug/test_build_base +CARGO_TARGET_DIR=${CARGO_TARGET_DIR:-$PWD/target} +PROFILE=${PROFILE:-debug} +BUILD_DIR=${CARGO_TARGET_DIR}/${PROFILE}/test_build_base + MY_DIR=$(dirname "$0") cd "$MY_DIR" || exit find . -name '*.rs' -exec ./update-references.sh "$BUILD_DIR" {} + From be1bc571c3558cf3920e77d5eb3f017aeeac637c Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Sat, 8 Feb 2020 16:44:35 -0800 Subject: [PATCH 024/243] Add `option-env-unwrap` lint --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 5 +++ clippy_lints/src/option_env_unwrap.rs | 55 +++++++++++++++++++++++++++ src/lintlist/mod.rs | 9 ++++- tests/ui/option_env_unwrap.rs | 12 ++++++ tests/ui/option_env_unwrap.stderr | 23 +++++++++++ 7 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 clippy_lints/src/option_env_unwrap.rs create mode 100644 tests/ui/option_env_unwrap.rs create mode 100644 tests/ui/option_env_unwrap.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 0953432bfad7..3658df88d40d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1276,6 +1276,7 @@ Released 2018-09-13 [`op_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#op_ref [`option_and_then_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_and_then_some [`option_as_ref_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref +[`option_env_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_env_unwrap [`option_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_expect_used [`option_map_or_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_or_none [`option_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unit_fn diff --git a/README.md b/README.md index 96584dfef5c6..fd7f33f91d51 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 354 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 355 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 5084e4e599c2..f900a99f314d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -267,6 +267,7 @@ pub mod no_effect; pub mod non_copy_const; pub mod non_expressive_names; pub mod open_options; +pub mod option_env_unwrap; pub mod overflow_check_conditional; pub mod panic_unimplemented; pub mod partialeq_ne_impl; @@ -713,6 +714,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &non_expressive_names::MANY_SINGLE_CHAR_NAMES, &non_expressive_names::SIMILAR_NAMES, &open_options::NONSENSICAL_OPEN_OPTIONS, + &option_env_unwrap::OPTION_ENV_UNWRAP, &overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, &panic_unimplemented::PANIC, &panic_unimplemented::PANIC_PARAMS, @@ -1003,6 +1005,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: let max_fn_params_bools = conf.max_fn_params_bools; let max_struct_bools = conf.max_struct_bools; store.register_early_pass(move || box excessive_bools::ExcessiveBools::new(max_struct_bools, max_fn_params_bools)); + store.register_early_pass(|| box option_env_unwrap::OptionEnvUnwrap); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1285,6 +1288,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), LintId::of(&non_expressive_names::MANY_SINGLE_CHAR_NAMES), LintId::of(&open_options::NONSENSICAL_OPEN_OPTIONS), + LintId::of(&option_env_unwrap::OPTION_ENV_UNWRAP), LintId::of(&overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL), LintId::of(&panic_unimplemented::PANIC_PARAMS), LintId::of(&partialeq_ne_impl::PARTIALEQ_NE_IMPL), @@ -1590,6 +1594,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&non_copy_const::BORROW_INTERIOR_MUTABLE_CONST), LintId::of(&non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST), LintId::of(&open_options::NONSENSICAL_OPEN_OPTIONS), + LintId::of(&option_env_unwrap::OPTION_ENV_UNWRAP), LintId::of(&ptr::MUT_FROM_REF), LintId::of(®ex::INVALID_REGEX), LintId::of(&serde_api::SERDE_API_MISUSE), diff --git a/clippy_lints/src/option_env_unwrap.rs b/clippy_lints/src/option_env_unwrap.rs new file mode 100644 index 000000000000..e0e8a95acd58 --- /dev/null +++ b/clippy_lints/src/option_env_unwrap.rs @@ -0,0 +1,55 @@ +use crate::utils::{is_direct_expn_of, span_lint_and_help}; +use if_chain::if_chain; +use rustc::lint::in_external_macro; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use syntax::ast::*; + +declare_clippy_lint! { + /// **What it does:** Checks for usage of `option_env!(...).unwrap()` and + /// suggests usage of the `env!` macro. + /// + /// **Why is this bad?** Unwrapping the result of `option_env!` will panic + /// at run-time if the environment variable doesn't exist, whereas `env!` + /// catches it at compile-time. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust,no_run + /// let _ = option_env!("HOME").unwrap(); + /// ``` + /// + /// Is better expressed as: + /// + /// ```rust,no_run + /// let _ = env!("HOME"); + /// ``` + pub OPTION_ENV_UNWRAP, + correctness, + "using `option_env!(...).unwrap()` to get environment variable" +} + +declare_lint_pass!(OptionEnvUnwrap => [OPTION_ENV_UNWRAP]); + +impl EarlyLintPass for OptionEnvUnwrap { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { + if_chain! { + if !in_external_macro(cx.sess, expr.span); + if let ExprKind::MethodCall(path_segment, args) = &expr.kind; + if path_segment.ident.as_str() == "unwrap"; + if let ExprKind::Call(caller, _) = &args[0].kind; + if is_direct_expn_of(caller.span, "option_env").is_some(); + then { + span_lint_and_help( + cx, + OPTION_ENV_UNWRAP, + expr.span, + "this will panic at run-time if the environment variable doesn't exist", + "consider using the `env!` macro instead" + ); + } + } + } +} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index f725ce2563fa..d4f94a9b60a4 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -6,7 +6,7 @@ pub use lint::Lint; pub use lint::LINT_LEVELS; // begin lint list, do not remove this comment, it’s used in `update_lints` -pub const ALL_LINTS: [Lint; 354] = [ +pub const ALL_LINTS: [Lint; 355] = [ Lint { name: "absurd_extreme_comparisons", group: "correctness", @@ -1498,6 +1498,13 @@ pub const ALL_LINTS: [Lint; 354] = [ deprecation: None, module: "methods", }, + Lint { + name: "option_env_unwrap", + group: "correctness", + desc: "using `option_env!(...).unwrap()` to get environment variable", + deprecation: None, + module: "option_env_unwrap", + }, Lint { name: "option_expect_used", group: "restriction", diff --git a/tests/ui/option_env_unwrap.rs b/tests/ui/option_env_unwrap.rs new file mode 100644 index 000000000000..2830669ff66b --- /dev/null +++ b/tests/ui/option_env_unwrap.rs @@ -0,0 +1,12 @@ +#![warn(clippy::option_env_unwrap)] + +macro_rules! option_env_unwrap { + ($env: expr) => { + option_env!($env).unwrap() + }; +} + +fn main() { + let _ = option_env!("HOME").unwrap(); + let _ = option_env_unwrap!("HOME"); +} diff --git a/tests/ui/option_env_unwrap.stderr b/tests/ui/option_env_unwrap.stderr new file mode 100644 index 000000000000..b7d5ecd6321e --- /dev/null +++ b/tests/ui/option_env_unwrap.stderr @@ -0,0 +1,23 @@ +error: this will panic at run-time if the environment variable doesn't exist + --> $DIR/option_env_unwrap.rs:10:13 + | +LL | let _ = option_env!("HOME").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::option-env-unwrap` implied by `-D warnings` + = help: consider using the `env!` macro instead + +error: this will panic at run-time if the environment variable doesn't exist + --> $DIR/option_env_unwrap.rs:5:9 + | +LL | option_env!($env).unwrap() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | let _ = option_env_unwrap!("HOME"); + | -------------------------- in this macro invocation + | + = help: consider using the `env!` macro instead + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + From 5328b5d6670a387a4c0f06404e476570ee739c63 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sun, 9 Feb 2020 15:31:47 +0700 Subject: [PATCH 025/243] Rustup "index ReEmpty by universe" --- clippy_lints/src/needless_pass_by_value.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index b23e26b75586..0e844b920712 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -170,8 +170,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { ( preds.iter().any(|t| t.def_id() == borrow_trait), - !preds.is_empty() - && preds.iter().all(|t| { + !preds.is_empty() && { + let ty_empty_region = cx.tcx.mk_imm_ref(&RegionKind::ReEmpty(ty::UniverseIndex::ROOT), ty); + preds.iter().all(|t| { let ty_params = &t .skip_binder() .trait_ref @@ -180,8 +181,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { .skip(1) .cloned() .collect::>(); - implements_trait(cx, cx.tcx.mk_imm_ref(&RegionKind::ReEmpty, ty), t.def_id(), ty_params) - }), + implements_trait(cx, ty_empty_region, t.def_id(), ty_params) + }) + }, ) }; From 9eb913a7e227e4c11ca0c2c7d8fd7ca22ed9c466 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sun, 9 Feb 2020 12:00:49 +0700 Subject: [PATCH 026/243] Fix error E0460 when compiled on Rustc repo --- tests/cargo/mod.rs | 74 ++++++++------------------------------- tests/compile-test.rs | 80 +++++++++++++++++++++++++++++++------------ tests/dogfood.rs | 13 ++++--- 3 files changed, 78 insertions(+), 89 deletions(-) diff --git a/tests/cargo/mod.rs b/tests/cargo/mod.rs index 5b2de05cb174..9973d5b84434 100644 --- a/tests/cargo/mod.rs +++ b/tests/cargo/mod.rs @@ -1,75 +1,29 @@ -use cargo_metadata::{Message::CompilerArtifact, MetadataCommand}; +use lazy_static::lazy_static; use std::env; -use std::ffi::OsStr; -use std::mem; use std::path::PathBuf; -use std::process::Command; -pub struct BuildInfo { - cargo_target_dir: PathBuf, -} - -impl BuildInfo { - pub fn new() -> Self { - let data = MetadataCommand::new().exec().unwrap(); - Self { - cargo_target_dir: data.target_directory, +lazy_static! { + pub static ref CARGO_TARGET_DIR: PathBuf = { + match env::var_os("CARGO_TARGET_DIR") { + Some(v) => v.into(), + None => "target".into(), } - } - - pub fn host_lib(&self) -> PathBuf { - if let Some(path) = option_env!("HOST_LIBS") { - PathBuf::from(path) - } else { - self.cargo_target_dir.join(env!("PROFILE")) - } - } - - pub fn target_lib(&self) -> PathBuf { + }; + pub static ref TARGET_LIB: PathBuf = { if let Some(path) = option_env!("TARGET_LIBS") { path.into() } else { - let mut dir = self.cargo_target_dir.clone(); + let mut dir = CARGO_TARGET_DIR.clone(); if let Some(target) = env::var_os("CARGO_BUILD_TARGET") { dir.push(target); } dir.push(env!("PROFILE")); dir } - } - - pub fn clippy_driver_path(&self) -> PathBuf { - if let Some(path) = option_env!("CLIPPY_DRIVER_PATH") { - PathBuf::from(path) - } else { - self.target_lib().join("clippy-driver") - } - } - - // When we'll want to use `extern crate ..` for a dependency that is used - // both by the crate and the compiler itself, we can't simply pass -L flags - // as we'll get a duplicate matching versions. Instead, disambiguate with - // `--extern dep=path`. - // See https://github.com/rust-lang/rust-clippy/issues/4015. - pub fn third_party_crates() -> Vec<(&'static str, PathBuf)> { - const THIRD_PARTY_CRATES: [&str; 4] = ["serde", "serde_derive", "regex", "clippy_lints"]; - let cargo = env::var_os("CARGO"); - let cargo = cargo.as_deref().unwrap_or_else(|| OsStr::new("cargo")); - let output = Command::new(cargo) - .arg("build") - .arg("--test=compile-test") - .arg("--message-format=json") - .output() - .unwrap(); + }; +} - let mut crates = Vec::with_capacity(THIRD_PARTY_CRATES.len()); - for message in cargo_metadata::parse_messages(output.stdout.as_slice()) { - if let CompilerArtifact(mut artifact) = message.unwrap() { - if let Some(&krate) = THIRD_PARTY_CRATES.iter().find(|&&krate| krate == artifact.target.name) { - crates.push((krate, mem::take(&mut artifact.filenames[0]))); - } - } - } - crates - } +#[must_use] +pub fn is_rustc_test_suite() -> bool { + option_env!("RUSTC_TEST_SUITE").is_some() } diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 7cfbfcf16a99..de2cf6d7873f 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -1,4 +1,4 @@ -#![feature(test)] +#![feature(test)] // compiletest_rs requires this attribute use compiletest_rs as compiletest; use compiletest_rs::common::Mode as TestMode; @@ -11,51 +11,87 @@ use std::path::{Path, PathBuf}; mod cargo; -#[must_use] -fn rustc_test_suite() -> Option { - option_env!("RUSTC_TEST_SUITE").map(PathBuf::from) +fn host_lib() -> PathBuf { + if let Some(path) = option_env!("HOST_LIBS") { + PathBuf::from(path) + } else { + cargo::CARGO_TARGET_DIR.join(env!("PROFILE")) + } } -#[must_use] -fn rustc_lib_path() -> PathBuf { - option_env!("RUSTC_LIB_PATH").unwrap().into() +fn clippy_driver_path() -> PathBuf { + if let Some(path) = option_env!("CLIPPY_DRIVER_PATH") { + PathBuf::from(path) + } else { + cargo::TARGET_LIB.join("clippy-driver") + } +} + +// When we'll want to use `extern crate ..` for a dependency that is used +// both by the crate and the compiler itself, we can't simply pass -L flags +// as we'll get a duplicate matching versions. Instead, disambiguate with +// `--extern dep=path`. +// See https://github.com/rust-lang/rust-clippy/issues/4015. +// +// FIXME: We cannot use `cargo build --message-format=json` to resolve to dependency files. +// Because it would force-rebuild if the options passed to `build` command is not the same +// as what we manually pass to `cargo` invocation +fn third_party_crates() -> String { + use std::collections::HashMap; + static CRATES: &[&str] = &["serde", "serde_derive", "regex", "clippy_lints"]; + let dep_dir = cargo::TARGET_LIB.join("deps"); + let mut crates: HashMap<&str, PathBuf> = HashMap::with_capacity(CRATES.len()); + for entry in fs::read_dir(dep_dir).unwrap() { + let path = match entry { + Ok(entry) => entry.path(), + _ => continue, + }; + if let Some(name) = path.file_name().and_then(OsStr::to_str) { + for dep in CRATES { + if name.starts_with(&format!("lib{}-", dep)) && name.ends_with(".rlib") { + crates.entry(dep).or_insert(path); + break; + } + } + } + } + + let v: Vec<_> = crates + .into_iter() + .map(|(dep, path)| format!("--extern {}={}", dep, path.display())) + .collect(); + v.join(" ") } fn default_config() -> compiletest::Config { - let build_info = cargo::BuildInfo::new(); let mut config = compiletest::Config::default(); if let Ok(name) = env::var("TESTNAME") { config.filter = Some(name); } - if rustc_test_suite().is_some() { - let path = rustc_lib_path(); + if let Some(path) = option_env!("RUSTC_LIB_PATH") { + let path = PathBuf::from(path); config.run_lib_path = path.clone(); config.compile_lib_path = path; } - let disambiguated: Vec<_> = cargo::BuildInfo::third_party_crates() - .iter() - .map(|(krate, path)| format!("--extern {}={}", krate, path.display())) - .collect(); - config.target_rustcflags = Some(format!( "-L {0} -L {1} -Dwarnings -Zui-testing {2}", - build_info.host_lib().join("deps").display(), - build_info.target_lib().join("deps").display(), - disambiguated.join(" ") + host_lib().join("deps").display(), + cargo::TARGET_LIB.join("deps").display(), + third_party_crates(), )); - config.build_base = if rustc_test_suite().is_some() { - // we don't need access to the stderr files on travis + config.build_base = if cargo::is_rustc_test_suite() { + // This make the stderr files go to clippy OUT_DIR on rustc repo build dir let mut path = PathBuf::from(env!("OUT_DIR")); path.push("test_build_base"); path } else { - build_info.host_lib().join("test_build_base") + host_lib().join("test_build_base") }; - config.rustc_path = build_info.clippy_driver_path(); + config.rustc_path = clippy_driver_path(); config } diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 5458143ab1cc..81af3d3033b2 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -1,21 +1,20 @@ +// Dogfood cannot run on Windows +#![cfg(not(windows))] + use lazy_static::lazy_static; use std::path::PathBuf; use std::process::Command; -#[allow(dead_code)] mod cargo; lazy_static! { - static ref CLIPPY_PATH: PathBuf = { - let build_info = cargo::BuildInfo::new(); - build_info.target_lib().join("cargo-clippy") - }; + static ref CLIPPY_PATH: PathBuf = cargo::TARGET_LIB.join("cargo-clippy"); } #[test] fn dogfood_clippy() { // run clippy on itself and fail the test if lint warnings are reported - if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) { + if cargo::is_rustc_test_suite() { return; } let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); @@ -44,7 +43,7 @@ fn dogfood_clippy() { #[test] fn dogfood_subprojects() { // run clippy on remaining subprojects and fail the test if lint warnings are reported - if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) { + if cargo::is_rustc_test_suite() { return; } let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); From 0e5ba2f0e7c1ec47ad1300e7065b97d5bc603c7c Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Sun, 9 Feb 2020 08:54:23 -0800 Subject: [PATCH 027/243] Account for `expect` being used to unwrap `Option` --- clippy_lints/src/option_env_unwrap.rs | 5 +++-- tests/ui/option_env_unwrap.rs | 5 +++++ tests/ui/option_env_unwrap.stderr | 28 +++++++++++++++++++++++---- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/option_env_unwrap.rs b/clippy_lints/src/option_env_unwrap.rs index e0e8a95acd58..e84a7dd2db04 100644 --- a/clippy_lints/src/option_env_unwrap.rs +++ b/clippy_lints/src/option_env_unwrap.rs @@ -38,7 +38,8 @@ impl EarlyLintPass for OptionEnvUnwrap { if_chain! { if !in_external_macro(cx.sess, expr.span); if let ExprKind::MethodCall(path_segment, args) = &expr.kind; - if path_segment.ident.as_str() == "unwrap"; + let method_name = path_segment.ident.as_str(); + if method_name == "expect" || method_name == "unwrap"; if let ExprKind::Call(caller, _) = &args[0].kind; if is_direct_expn_of(caller.span, "option_env").is_some(); then { @@ -46,7 +47,7 @@ impl EarlyLintPass for OptionEnvUnwrap { cx, OPTION_ENV_UNWRAP, expr.span, - "this will panic at run-time if the environment variable doesn't exist", + "this will panic at run-time if the environment variable doesn't exist at compile-time", "consider using the `env!` macro instead" ); } diff --git a/tests/ui/option_env_unwrap.rs b/tests/ui/option_env_unwrap.rs index 2830669ff66b..c8488da505cc 100644 --- a/tests/ui/option_env_unwrap.rs +++ b/tests/ui/option_env_unwrap.rs @@ -4,9 +4,14 @@ macro_rules! option_env_unwrap { ($env: expr) => { option_env!($env).unwrap() }; + ($env: expr, $message: expr) => { + option_env!($env).expect($message) + }; } fn main() { let _ = option_env!("HOME").unwrap(); + let _ = option_env!("HOME").expect("environment variable HOME isn't set"); let _ = option_env_unwrap!("HOME"); + let _ = option_env_unwrap!("HOME", "environment variable HOME isn't set"); } diff --git a/tests/ui/option_env_unwrap.stderr b/tests/ui/option_env_unwrap.stderr index b7d5ecd6321e..2230cc3d8592 100644 --- a/tests/ui/option_env_unwrap.stderr +++ b/tests/ui/option_env_unwrap.stderr @@ -1,5 +1,5 @@ -error: this will panic at run-time if the environment variable doesn't exist - --> $DIR/option_env_unwrap.rs:10:13 +error: this will panic at run-time if the environment variable doesn't exist at compile-time + --> $DIR/option_env_unwrap.rs:13:13 | LL | let _ = option_env!("HOME").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,15 @@ LL | let _ = option_env!("HOME").unwrap(); = note: `-D clippy::option-env-unwrap` implied by `-D warnings` = help: consider using the `env!` macro instead -error: this will panic at run-time if the environment variable doesn't exist +error: this will panic at run-time if the environment variable doesn't exist at compile-time + --> $DIR/option_env_unwrap.rs:14:13 + | +LL | let _ = option_env!("HOME").expect("environment variable HOME isn't set"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using the `env!` macro instead + +error: this will panic at run-time if the environment variable doesn't exist at compile-time --> $DIR/option_env_unwrap.rs:5:9 | LL | option_env!($env).unwrap() @@ -19,5 +27,17 @@ LL | let _ = option_env_unwrap!("HOME"); = help: consider using the `env!` macro instead = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 2 previous errors +error: this will panic at run-time if the environment variable doesn't exist at compile-time + --> $DIR/option_env_unwrap.rs:8:9 + | +LL | option_env!($env).expect($message) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | let _ = option_env_unwrap!("HOME", "environment variable HOME isn't set"); + | ----------------------------------------------------------------- in this macro invocation + | + = help: consider using the `env!` macro instead + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors From a3a1587a1c5b7df413729e34923ada495f3fff94 Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Sun, 9 Feb 2020 10:58:08 -0800 Subject: [PATCH 028/243] Allow `option-env-unwrap` within external macros --- clippy_lints/src/option_env_unwrap.rs | 2 -- tests/ui/auxiliary/macro_rules.rs | 10 ++++++++++ tests/ui/option_env_unwrap.rs | 6 ++++++ tests/ui/option_env_unwrap.stderr | 28 ++++++++++++++++++++++----- 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/option_env_unwrap.rs b/clippy_lints/src/option_env_unwrap.rs index e84a7dd2db04..1af7793499f6 100644 --- a/clippy_lints/src/option_env_unwrap.rs +++ b/clippy_lints/src/option_env_unwrap.rs @@ -1,6 +1,5 @@ use crate::utils::{is_direct_expn_of, span_lint_and_help}; use if_chain::if_chain; -use rustc::lint::in_external_macro; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use syntax::ast::*; @@ -36,7 +35,6 @@ declare_lint_pass!(OptionEnvUnwrap => [OPTION_ENV_UNWRAP]); impl EarlyLintPass for OptionEnvUnwrap { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { if_chain! { - if !in_external_macro(cx.sess, expr.span); if let ExprKind::MethodCall(path_segment, args) = &expr.kind; let method_name = path_segment.ident.as_str(); if method_name == "expect" || method_name == "unwrap"; diff --git a/tests/ui/auxiliary/macro_rules.rs b/tests/ui/auxiliary/macro_rules.rs index eafc68bd6bcf..0bbb9534928e 100644 --- a/tests/ui/auxiliary/macro_rules.rs +++ b/tests/ui/auxiliary/macro_rules.rs @@ -46,3 +46,13 @@ macro_rules! take_external { std::mem::replace($s, Default::default()) }; } + +#[macro_export] +macro_rules! option_env_unwrap_external { + ($env: expr) => { + option_env!($env).unwrap() + }; + ($env: expr, $message: expr) => { + option_env!($env).expect($message) + }; +} diff --git a/tests/ui/option_env_unwrap.rs b/tests/ui/option_env_unwrap.rs index c8488da505cc..59463f9a5561 100644 --- a/tests/ui/option_env_unwrap.rs +++ b/tests/ui/option_env_unwrap.rs @@ -1,5 +1,9 @@ +// aux-build:macro_rules.rs #![warn(clippy::option_env_unwrap)] +#[macro_use] +extern crate macro_rules; + macro_rules! option_env_unwrap { ($env: expr) => { option_env!($env).unwrap() @@ -14,4 +18,6 @@ fn main() { let _ = option_env!("HOME").expect("environment variable HOME isn't set"); let _ = option_env_unwrap!("HOME"); let _ = option_env_unwrap!("HOME", "environment variable HOME isn't set"); + let _ = option_env_unwrap_external!("HOME"); + let _ = option_env_unwrap_external!("HOME", "environment variable HOME isn't set"); } diff --git a/tests/ui/option_env_unwrap.stderr b/tests/ui/option_env_unwrap.stderr index 2230cc3d8592..3a2d5d114233 100644 --- a/tests/ui/option_env_unwrap.stderr +++ b/tests/ui/option_env_unwrap.stderr @@ -1,5 +1,5 @@ error: this will panic at run-time if the environment variable doesn't exist at compile-time - --> $DIR/option_env_unwrap.rs:13:13 + --> $DIR/option_env_unwrap.rs:17:13 | LL | let _ = option_env!("HOME").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let _ = option_env!("HOME").unwrap(); = help: consider using the `env!` macro instead error: this will panic at run-time if the environment variable doesn't exist at compile-time - --> $DIR/option_env_unwrap.rs:14:13 + --> $DIR/option_env_unwrap.rs:18:13 | LL | let _ = option_env!("HOME").expect("environment variable HOME isn't set"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | let _ = option_env!("HOME").expect("environment variable HOME isn't set = help: consider using the `env!` macro instead error: this will panic at run-time if the environment variable doesn't exist at compile-time - --> $DIR/option_env_unwrap.rs:5:9 + --> $DIR/option_env_unwrap.rs:9:9 | LL | option_env!($env).unwrap() | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | let _ = option_env_unwrap!("HOME"); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: this will panic at run-time if the environment variable doesn't exist at compile-time - --> $DIR/option_env_unwrap.rs:8:9 + --> $DIR/option_env_unwrap.rs:12:9 | LL | option_env!($env).expect($message) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -39,5 +39,23 @@ LL | let _ = option_env_unwrap!("HOME", "environment variable HOME isn't set = help: consider using the `env!` macro instead = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 4 previous errors +error: this will panic at run-time if the environment variable doesn't exist at compile-time + --> $DIR/option_env_unwrap.rs:21:13 + | +LL | let _ = option_env_unwrap_external!("HOME"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using the `env!` macro instead + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: this will panic at run-time if the environment variable doesn't exist at compile-time + --> $DIR/option_env_unwrap.rs:22:13 + | +LL | let _ = option_env_unwrap_external!("HOME", "environment variable HOME isn't set"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using the `env!` macro instead + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors From 46bd185e32b03916be15fca6ddd7c6d011795ac8 Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Sun, 9 Feb 2020 14:44:17 -0800 Subject: [PATCH 029/243] Rustup to rust-lang/rust#68911 --- clippy_lints/src/len_zero.rs | 3 ++- clippy_lints/src/use_self.rs | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index b522a74fb0e8..2d381148012c 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -279,7 +279,7 @@ fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { cx.tcx .inherent_impls(id) .iter() - .any(|imp| cx.tcx.associated_items(*imp).any(|item| is_is_empty(cx, &item))) + .any(|imp| cx.tcx.associated_items(*imp).iter().any(|item| is_is_empty(cx, &item))) } let ty = &walk_ptrs_ty(cx.tables.expr_ty(expr)); @@ -288,6 +288,7 @@ fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { if let Some(principal) = tt.principal() { cx.tcx .associated_items(principal.def_id()) + .iter() .any(|item| is_is_empty(cx, &item)) } else { false diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 4160370dd15a..9be070bd3d15 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -125,6 +125,7 @@ fn check_trait_method_impl_decl<'a, 'tcx>( let trait_method = cx .tcx .associated_items(impl_trait_ref.def_id) + .iter() .find(|assoc_item| { assoc_item.kind == ty::AssocKind::Method && cx From b48b221f809343bd4da8242a1ea456efd76f3f90 Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Sun, 9 Feb 2020 14:12:40 -0800 Subject: [PATCH 030/243] Use `PATH` environment variable for testing The tests were failing on windows because the `HOME` env variable doesn't exist on it so using the `PATH` variable to test instead. --- tests/ui/option_env_unwrap.rs | 12 ++++++------ tests/ui/option_env_unwrap.stderr | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/ui/option_env_unwrap.rs b/tests/ui/option_env_unwrap.rs index 59463f9a5561..642c77460a34 100644 --- a/tests/ui/option_env_unwrap.rs +++ b/tests/ui/option_env_unwrap.rs @@ -14,10 +14,10 @@ macro_rules! option_env_unwrap { } fn main() { - let _ = option_env!("HOME").unwrap(); - let _ = option_env!("HOME").expect("environment variable HOME isn't set"); - let _ = option_env_unwrap!("HOME"); - let _ = option_env_unwrap!("HOME", "environment variable HOME isn't set"); - let _ = option_env_unwrap_external!("HOME"); - let _ = option_env_unwrap_external!("HOME", "environment variable HOME isn't set"); + let _ = option_env!("PATH").unwrap(); + let _ = option_env!("PATH").expect("environment variable PATH isn't set"); + let _ = option_env_unwrap!("PATH"); + let _ = option_env_unwrap!("PATH", "environment variable PATH isn't set"); + let _ = option_env_unwrap_external!("PATH"); + let _ = option_env_unwrap_external!("PATH", "environment variable PATH isn't set"); } diff --git a/tests/ui/option_env_unwrap.stderr b/tests/ui/option_env_unwrap.stderr index 3a2d5d114233..8de9c8a9d29e 100644 --- a/tests/ui/option_env_unwrap.stderr +++ b/tests/ui/option_env_unwrap.stderr @@ -1,7 +1,7 @@ error: this will panic at run-time if the environment variable doesn't exist at compile-time --> $DIR/option_env_unwrap.rs:17:13 | -LL | let _ = option_env!("HOME").unwrap(); +LL | let _ = option_env!("PATH").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::option-env-unwrap` implied by `-D warnings` @@ -10,7 +10,7 @@ LL | let _ = option_env!("HOME").unwrap(); error: this will panic at run-time if the environment variable doesn't exist at compile-time --> $DIR/option_env_unwrap.rs:18:13 | -LL | let _ = option_env!("HOME").expect("environment variable HOME isn't set"); +LL | let _ = option_env!("PATH").expect("environment variable PATH isn't set"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using the `env!` macro instead @@ -21,7 +21,7 @@ error: this will panic at run-time if the environment variable doesn't exist at LL | option_env!($env).unwrap() | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | let _ = option_env_unwrap!("HOME"); +LL | let _ = option_env_unwrap!("PATH"); | -------------------------- in this macro invocation | = help: consider using the `env!` macro instead @@ -33,7 +33,7 @@ error: this will panic at run-time if the environment variable doesn't exist at LL | option_env!($env).expect($message) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | let _ = option_env_unwrap!("HOME", "environment variable HOME isn't set"); +LL | let _ = option_env_unwrap!("PATH", "environment variable PATH isn't set"); | ----------------------------------------------------------------- in this macro invocation | = help: consider using the `env!` macro instead @@ -42,7 +42,7 @@ LL | let _ = option_env_unwrap!("HOME", "environment variable HOME isn't set error: this will panic at run-time if the environment variable doesn't exist at compile-time --> $DIR/option_env_unwrap.rs:21:13 | -LL | let _ = option_env_unwrap_external!("HOME"); +LL | let _ = option_env_unwrap_external!("PATH"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using the `env!` macro instead @@ -51,7 +51,7 @@ LL | let _ = option_env_unwrap_external!("HOME"); error: this will panic at run-time if the environment variable doesn't exist at compile-time --> $DIR/option_env_unwrap.rs:22:13 | -LL | let _ = option_env_unwrap_external!("HOME", "environment variable HOME isn't set"); +LL | let _ = option_env_unwrap_external!("PATH", "environment variable PATH isn't set"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider using the `env!` macro instead From f940b04de6524f94140f3630434f89034e0a6481 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 10 Feb 2020 15:51:51 +0100 Subject: [PATCH 031/243] Fix run-pass tests when CARGO_TARGET_DIR is not set --- tests/cargo/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/cargo/mod.rs b/tests/cargo/mod.rs index 9973d5b84434..5f06a97d3e98 100644 --- a/tests/cargo/mod.rs +++ b/tests/cargo/mod.rs @@ -1,3 +1,4 @@ +use cargo_metadata::MetadataCommand; use lazy_static::lazy_static; use std::env; use std::path::PathBuf; @@ -6,7 +7,7 @@ lazy_static! { pub static ref CARGO_TARGET_DIR: PathBuf = { match env::var_os("CARGO_TARGET_DIR") { Some(v) => v.into(), - None => "target".into(), + None => MetadataCommand::new().exec().unwrap().target_directory, } }; pub static ref TARGET_LIB: PathBuf = { From 57b636422a247228523185f65f4f827fc9270d0c Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 10 Feb 2020 15:59:14 +0100 Subject: [PATCH 032/243] Rustup to rust-lang/rust#68725 --- clippy_lints/src/utils/diagnostics.rs | 87 +++++++++++++++------------ 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/clippy_lints/src/utils/diagnostics.rs b/clippy_lints/src/utils/diagnostics.rs index 9739b118f749..cc519d525521 100644 --- a/clippy_lints/src/utils/diagnostics.rs +++ b/clippy_lints/src/utils/diagnostics.rs @@ -6,27 +6,16 @@ use rustc_lint::{LateContext, Lint, LintContext}; use rustc_span::source_map::{MultiSpan, Span}; use std::env; -/// Wrapper around `DiagnosticBuilder` that adds a link to Clippy documentation for the emitted lint -struct DiagnosticWrapper<'a>(DiagnosticBuilder<'a>); - -impl<'a> Drop for DiagnosticWrapper<'a> { - fn drop(&mut self) { - self.0.emit(); - } -} - -impl<'a> DiagnosticWrapper<'a> { - fn docs_link(&mut self, lint: &'static Lint) { - if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() { - self.0.help(&format!( - "for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{}", - &option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| { - // extract just major + minor version and ignore patch versions - format!("rust-{}", n.rsplitn(2, '.').nth(1).unwrap()) - }), - lint.name_lower().replacen("clippy::", "", 1) - )); - } +fn docs_link(db: &mut DiagnosticBuilder<'_>, lint: &'static Lint) { + if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() { + db.help(&format!( + "for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{}", + &option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| { + // extract just major + minor version and ignore patch versions + format!("rust-{}", n.rsplitn(2, '.').nth(1).unwrap()) + }), + lint.name_lower().replacen("clippy::", "", 1) + )); } } @@ -48,7 +37,11 @@ impl<'a> DiagnosticWrapper<'a> { /// | ^^^^^^^^^^^^^^^^^^^^^^^ /// ``` pub fn span_lint(cx: &T, lint: &'static Lint, sp: impl Into, msg: &str) { - DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)).docs_link(lint); + cx.struct_span_lint(lint, sp, |ldb| { + let mut db = ldb.build(msg); + docs_link(&mut db, lint); + db.emit(); + }); } /// Same as `span_lint` but with an extra `help` message. @@ -70,9 +63,12 @@ pub fn span_lint(cx: &T, lint: &'static Lint, sp: impl Into(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, help: &str) { - let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg)); - db.0.help(help); - db.docs_link(lint); + cx.struct_span_lint(lint, span, |ldb| { + let mut db = ldb.build(msg); + db.help(help); + docs_link(&mut db, lint); + db.emit(); + }); } /// Like `span_lint` but with a `note` section instead of a `help` message. @@ -104,26 +100,36 @@ pub fn span_lint_and_note<'a, T: LintContext>( note_span: Span, note: &str, ) { - let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg)); - if note_span == span { - db.0.note(note); - } else { - db.0.span_note(note_span, note); - } - db.docs_link(lint); + cx.struct_span_lint(lint, span, |ldb| { + let mut db = ldb.build(msg); + if note_span == span { + db.note(note); + } else { + db.span_note(note_span, note); + } + docs_link(&mut db, lint); + db.emit(); + }); } pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F) where F: for<'b> FnOnce(&mut DiagnosticBuilder<'b>), { - let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)); - f(&mut db.0); - db.docs_link(lint); + cx.struct_span_lint(lint, sp, |ldb| { + let mut db = ldb.build(msg); + f(&mut db); + docs_link(&mut db, lint); + db.emit(); + }); } pub fn span_lint_hir(cx: &LateContext<'_, '_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) { - DiagnosticWrapper(cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg)).docs_link(lint); + cx.tcx.struct_span_lint_hir(lint, hir_id, sp, |ldb| { + let mut db = ldb.build(msg); + docs_link(&mut db, lint); + db.emit(); + }); } pub fn span_lint_hir_and_then( @@ -134,9 +140,12 @@ pub fn span_lint_hir_and_then( msg: &str, f: impl FnOnce(&mut DiagnosticBuilder<'_>), ) { - let mut db = DiagnosticWrapper(cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg)); - f(&mut db.0); - db.docs_link(lint); + cx.tcx.struct_span_lint_hir(lint, hir_id, sp, |ldb| { + let mut db = ldb.build(msg); + f(&mut db); + docs_link(&mut db, lint); + db.emit(); + }); } /// Add a span lint with a suggestion on how to fix it. From c86c09b19a7db3749c2c43a9fa964aa45ac13af1 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Mon, 10 Feb 2020 16:42:50 +0100 Subject: [PATCH 033/243] Use current_dir instead of cargo_metadata Co-Authored-By: lzutao --- tests/cargo/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/cargo/mod.rs b/tests/cargo/mod.rs index 5f06a97d3e98..3c385343f701 100644 --- a/tests/cargo/mod.rs +++ b/tests/cargo/mod.rs @@ -1,4 +1,3 @@ -use cargo_metadata::MetadataCommand; use lazy_static::lazy_static; use std::env; use std::path::PathBuf; @@ -7,7 +6,7 @@ lazy_static! { pub static ref CARGO_TARGET_DIR: PathBuf = { match env::var_os("CARGO_TARGET_DIR") { Some(v) => v.into(), - None => MetadataCommand::new().exec().unwrap().target_directory, + None => env::current_dir().unwrap().join("target"), } }; pub static ref TARGET_LIB: PathBuf = { From 6b4cae18dde124dda30e53ade20b8d43315a6dc6 Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Mon, 10 Feb 2020 19:24:01 -0800 Subject: [PATCH 034/243] Remove unnecessary imports from `new_lint` tool --- clippy_dev/src/new_lint.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index 9d1f19f954b0..1149015cfb37 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -117,7 +117,7 @@ fn get_lint_file_contents( context_import: &str, ) -> String { format!( - "use rustc_lint::{{LintArray, LintPass, {type}, {context_import}}}; + "use rustc_lint::{{{type}, {context_import}}}; use rustc_session::{{declare_lint_pass, declare_tool_lint}}; {pass_import} From 1e117938cf12e59eaac89482e611ee4d95e2a953 Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Mon, 10 Feb 2020 19:37:25 -0800 Subject: [PATCH 035/243] Remove unnecessary imports from documentation --- CONTRIBUTING.md | 2 +- doc/adding_lints.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4a828051185f..68eb64c94b6d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -110,7 +110,7 @@ It's worth noting that the majority of `clippy_lints/src/lib.rs` is autogenerate ```rust // ./clippy_lints/src/else_if_without_else.rs -use rustc::lint::{EarlyLintPass, LintArray, LintPass}; +use rustc_lint::{EarlyLintPass, EarlyContext}; // ... diff --git a/doc/adding_lints.md b/doc/adding_lints.md index 99178c2d75b9..e1f4ce016c5c 100644 --- a/doc/adding_lints.md +++ b/doc/adding_lints.md @@ -138,7 +138,7 @@ at `clippy_lints/src/foo_functions.rs`. That's the crate where all the lint code is. This file has already imported some initial things we will need: ```rust -use rustc::lint::{LintArray, LintPass, EarlyLintPass, EarlyContext}; +use rustc_lint::{EarlyLintPass, EarlyContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use syntax::ast::*; ``` From fcc3e7238fc303881d7e3f06f423a0b105318bf0 Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Tue, 11 Feb 2020 06:20:47 -0800 Subject: [PATCH 036/243] Remove unnecessary imports from tests --- tests/ui/default_lint.rs | 1 - tests/ui/default_lint.stderr | 2 +- tests/ui/lint_without_lint_pass.rs | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/ui/default_lint.rs b/tests/ui/default_lint.rs index 988a7b866dea..0c6f29a43c6d 100644 --- a/tests/ui/default_lint.rs +++ b/tests/ui/default_lint.rs @@ -6,7 +6,6 @@ extern crate rustc; #[macro_use] extern crate rustc_session; extern crate rustc_lint; -use rustc_lint::{LintArray, LintPass}; declare_tool_lint! { pub clippy::TEST_LINT, diff --git a/tests/ui/default_lint.stderr b/tests/ui/default_lint.stderr index fc76dec82223..5c5836a7d297 100644 --- a/tests/ui/default_lint.stderr +++ b/tests/ui/default_lint.stderr @@ -1,5 +1,5 @@ error: the lint `TEST_LINT_DEFAULT` has the default lint description - --> $DIR/default_lint.rs:18:1 + --> $DIR/default_lint.rs:17:1 | LL | / declare_tool_lint! { LL | | pub clippy::TEST_LINT_DEFAULT, diff --git a/tests/ui/lint_without_lint_pass.rs b/tests/ui/lint_without_lint_pass.rs index 5b0b4d12d134..8eb1f7b64610 100644 --- a/tests/ui/lint_without_lint_pass.rs +++ b/tests/ui/lint_without_lint_pass.rs @@ -6,7 +6,7 @@ extern crate rustc; #[macro_use] extern crate rustc_session; extern crate rustc_lint; -use rustc_lint::{LintArray, LintPass}; +use rustc_lint::LintPass; declare_tool_lint! { pub clippy::TEST_LINT, From bfc4bd4dbefaf3bd80eda2f3e764e03757fc9f46 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Tue, 11 Feb 2020 22:52:00 +0700 Subject: [PATCH 037/243] Impl DefaultCallbacks on our side --- src/driver.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index 27ff7fa9116e..087c8c67b4a0 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -63,10 +63,10 @@ fn test_arg_value() { assert_eq!(arg_value(args, "--foo", |_| true), None); } -#[allow(clippy::too_many_lines)] +struct DefaultCallbacks; +impl rustc_driver::Callbacks for DefaultCallbacks {} struct ClippyCallbacks; - impl rustc_driver::Callbacks for ClippyCallbacks { fn config(&mut self, config: &mut interface::Config) { let previous = config.register_lints.take(); @@ -387,7 +387,7 @@ pub fn main() { } } let mut clippy = ClippyCallbacks; - let mut default = rustc_driver::DefaultCallbacks; + let mut default = DefaultCallbacks; let callbacks: &mut (dyn rustc_driver::Callbacks + Send) = if clippy_enabled { &mut clippy } else { &mut default }; rustc_driver::run_compiler(&args, callbacks, None, None) From 2f8ef89a8bf362b9ff61cdb34b6000a939dafe98 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 20 Jan 2020 16:03:26 +0100 Subject: [PATCH 038/243] Add integration test GitHub action --- .github/workflows/integration.yml | 69 +++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 .github/workflows/integration.yml diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml new file mode 100644 index 000000000000..fc05ee9b9210 --- /dev/null +++ b/.github/workflows/integration.yml @@ -0,0 +1,69 @@ +name: Integration + +on: + push: + branches: + - auto + - try + # Don't run integration tests, when only textfiles were modified + paths-ignore: + - 'COPYRIGHT' + - 'LICENSE-*' + - '**.md' + - '**.txt' + +env: + RUST_BACKTRACE: 1 + +jobs: + integration: + strategy: + fail-fast: false + matrix: + integration: + - 'rust-lang/rls' + - 'rust-lang/cargo' + - 'rust-lang/chalk' + - 'Geal/nom' + - 'rust-lang/rustfmt' + - 'hyperium/hyper' + - 'rust-itertools/itertools' + - 'serde-rs/serde' + - 'rust-lang/stdarch' + - 'rust-random/rand' + - 'rust-lang/futures-rs' + - 'Marwes/combine' + - 'rust-lang-nursery/failure' + - 'rust-lang/log' + - 'chronotope/chrono' + runs-on: ubuntu-latest + + steps: + - name: rust-toolchain + uses: actions-rs/toolchain@v1.0.3 + with: + toolchain: nightly + target: x86_64-unknown-linux-gnu + profile: minimal + - name: Cache cargo dir + uses: actions/cache@v1 + with: + path: ~/.cargo + key: ${{ runner.os }}-x86_64-unknown-linux-gnu + - name: Checkout + uses: actions/checkout@v2.0.0 + - name: Master Toolchain Setup + run: bash setup-toolchain.sh + + - name: Build + run: cargo build --features integration + - name: Test ${{ matrix.integration }} + run: cargo test --test integration --features integration + env: + INTEGRATION: ${{ matrix.integration }} + + - name: Run cargo-cache --autoclean + run: | + cargo install cargo-cache --debug + find ~/.cargo/bin ! -type d -exec strip {} \; + cargo cache --autoclean From 1158c18ae74a2754329ad9192312c10b80293981 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 21 Jan 2020 13:46:53 +0100 Subject: [PATCH 039/243] Add clippy_dev checks to GitHub Actions --- .github/workflows/clippy_dev.yml | 44 ++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 .github/workflows/clippy_dev.yml diff --git a/.github/workflows/clippy_dev.yml b/.github/workflows/clippy_dev.yml new file mode 100644 index 000000000000..d054b6ba750c --- /dev/null +++ b/.github/workflows/clippy_dev.yml @@ -0,0 +1,44 @@ +name: Clippy Dev Test + +on: + # Only run on paths, that get checked by the clippy_dev tool + push: + paths: + - 'CAHNGELOG.md' + - 'README.md' + - '**.stderr' + - '**.rs' + pull_request: + paths: + - 'CAHNGELOG.md' + - 'README.md' + - '**.stderr' + - '**.rs' + +env: + RUST_BACKTRACE: 1 + +jobs: + clippy_dev: + runs-on: ubuntu-latest + + steps: + - name: rust-toolchain + uses: actions-rs/toolchain@v1.0.3 + with: + toolchain: nightly + target: x86_64-unknown-linux-gnu + profile: minimal + components: rustfmt + - name: Checkout + uses: actions/checkout@v2.0.0 + + - name: Build + run: cargo build --features deny-warnings + working-directory: clippy_dev + - name: Test limit-stderr-length + run: cargo dev --limit-stderr-length + - name: Test update_lints + run: cargo dev update_lints --check + - name: Test fmt + run: cargo dev fmt --check From 20c3319961e77e8dfcbf102a0616de500bd0cac1 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 21 Jan 2020 15:29:54 +0100 Subject: [PATCH 040/243] Add remark check to GHA --- .github/workflows/remark.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/workflows/remark.yml diff --git a/.github/workflows/remark.yml b/.github/workflows/remark.yml new file mode 100644 index 000000000000..8e311c75df08 --- /dev/null +++ b/.github/workflows/remark.yml @@ -0,0 +1,24 @@ +name: Remark + +on: + push: + paths: + - '**.md' + pull_request: + paths: + - '**.md' + +jobs: + remark: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2.0.0 + - name: Setup Node.js + uses: actions/setup-node@v1.1.0 + - name: Install remark + run: npm install remark-cli remark-lint remark-lint-maximum-line-length remark-preset-lint-recommended + + - name: Check *.md files + run: git ls-files -z '*.md' | xargs -0 -n 1 -I {} ./node_modules/.bin/remark {} -u lint -f > /dev/null From 2a7a3aa94647c14fd1e046b3dc183784de42af98 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 21 Jan 2020 16:32:25 +0100 Subject: [PATCH 041/243] Rename .remarkrc.json -> .remarkrc and fix file --- .remarkrc | 12 ++++++++++++ .remarkrc.json | 12 ------------ 2 files changed, 12 insertions(+), 12 deletions(-) create mode 100644 .remarkrc delete mode 100644 .remarkrc.json diff --git a/.remarkrc b/.remarkrc new file mode 100644 index 000000000000..0ede7ac75cb6 --- /dev/null +++ b/.remarkrc @@ -0,0 +1,12 @@ +{ + "plugins": [ + "remark-preset-lint-recommended", + ["remark-lint-list-item-indent", false], + ["remark-lint-no-literal-urls", false], + ["remark-lint-no-shortcut-reference-link", false], + ["remark-lint-maximum-line-length", 120] + ], + "settings": { + "commonmark": true + } +} diff --git a/.remarkrc.json b/.remarkrc.json deleted file mode 100644 index 22bae13ccf88..000000000000 --- a/.remarkrc.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "plugins": { - "lint": { - "table-pipes": false, - "table-pipe-alignment": false, - "maximum-line-length": 120 - } - }, - "settings": { - "commonmark": true - } -} From 757bbf7feb2e9ed1e4d8cc547390608654e8191e Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 21 Jan 2020 16:39:58 +0100 Subject: [PATCH 042/243] Fix markdown Files Rendered: [CHANGELOG.md](https://github.com/flip1995/rust-clippy/blob/gha/CHANGELOG.md) [CODE_OF_CONDUCT.md](https://github.com/flip1995/rust-clippy/blob/gha/CODE_OF_CONDUCT.md) [CONTRIBUTING.md](https://github.com/flip1995/rust-clippy/blob/gha/CONTRIBUTING.md) [README.md](https://github.com/flip1995/rust-clippy/blob/gha/README.md) [clippy_dummy/PUBLISH.md](https://github.com/flip1995/rust-clippy/blob/gha/clippy_dummy/PUBLISH.md) [doc/adding_lints.md](https://github.com/flip1995/rust-clippy/blob/gha/doc/adding_lints.md) [etc/relicense/RELICENSE_DOCUMENTATION.md](https://github.com/flip1995/rust-clippy/blob/gha/etc/relicense/RELICENSE_DOCUMENTATION.md) --- CHANGELOG.md | 105 ++++++++++++----------- CODE_OF_CONDUCT.md | 60 +++++++++---- CONTRIBUTING.md | 64 ++++++++------ README.md | 16 ++-- clippy_dummy/PUBLISH.md | 8 +- doc/adding_lints.md | 11 ++- etc/relicense/RELICENSE_DOCUMENTATION.md | 75 +++++++++++----- 7 files changed, 213 insertions(+), 126 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3658df88d40d..2f527a407db7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -203,29 +203,29 @@ Released 2019-07-04 [eb9f9b1...082cfa7](https://github.com/rust-lang/rust-clippy/compare/eb9f9b1...082cfa7) - * New lints: [`find_map`], [`filter_map_next`] [#4039](https://github.com/rust-lang/rust-clippy/pull/4039) - * New lint: [`path_buf_push_overwrite`] [#3954](https://github.com/rust-lang/rust-clippy/pull/3954) - * Move `path_buf_push_overwrite` to the nursery [#4013](https://github.com/rust-lang/rust-clippy/pull/4013) - * Split [`redundant_closure`] into [`redundant_closure`] and [`redundant_closure_for_method_calls`] [#4110](https://github.com/rust-lang/rust-clippy/pull/4101) - * Allow allowing of [`toplevel_ref_arg`] lint [#4007](https://github.com/rust-lang/rust-clippy/pull/4007) - * Fix false negative in [`or_fun_call`] pertaining to nested constructors [#4084](https://github.com/rust-lang/rust-clippy/pull/4084) - * Fix false positive in [`or_fn_call`] pertaining to enum variant constructors [#4018](https://github.com/rust-lang/rust-clippy/pull/4018) - * Fix false positive in [`useless_let_if_seq`] pertaining to interior mutability [#4035](https://github.com/rust-lang/rust-clippy/pull/4035) - * Fix false positive in [`redundant_closure`] pertaining to non-function types [#4008](https://github.com/rust-lang/rust-clippy/pull/4008) - * Fix false positive in [`let_and_return`] pertaining to attributes on `let`s [#4024](https://github.com/rust-lang/rust-clippy/pull/4024) - * Fix false positive in [`module_name_repetitions`] lint pertaining to attributes [#4006](https://github.com/rust-lang/rust-clippy/pull/4006) - * Fix false positive on [`assertions_on_constants`] pertaining to `debug_assert!` [#3989](https://github.com/rust-lang/rust-clippy/pull/3989) - * Improve suggestion in [`map_clone`] to suggest `.copied()` where applicable [#3970](https://github.com/rust-lang/rust-clippy/pull/3970) [#4043](https://github.com/rust-lang/rust-clippy/pull/4043) - * Improve suggestion for [`search_is_some`] [#4049](https://github.com/rust-lang/rust-clippy/pull/4049) - * Improve suggestion applicability for [`naive_bytecount`] [#3984](https://github.com/rust-lang/rust-clippy/pull/3984) - * Improve suggestion applicability for [`while_let_loop`] [#3975](https://github.com/rust-lang/rust-clippy/pull/3975) - * Improve diagnostics for [`too_many_arguments`] [#4053](https://github.com/rust-lang/rust-clippy/pull/4053) - * Improve diagnostics for [`cast_lossless`] [#4021](https://github.com/rust-lang/rust-clippy/pull/4021) - * Deal with macro checks in desugarings better [#4082](https://github.com/rust-lang/rust-clippy/pull/4082) - * Add macro check for [`unnecessary_cast`] [#4026](https://github.com/rust-lang/rust-clippy/pull/4026) - * Remove [`approx_constant`]'s documentation's "Known problems" section. [#4027](https://github.com/rust-lang/rust-clippy/pull/4027) - * Fix ICE in [`suspicious_else_formatting`] [#3960](https://github.com/rust-lang/rust-clippy/pull/3960) - * Fix ICE in [`decimal_literal_representation`] [#3931](https://github.com/rust-lang/rust-clippy/pull/3931) +* New lints: [`find_map`], [`filter_map_next`] [#4039](https://github.com/rust-lang/rust-clippy/pull/4039) +* New lint: [`path_buf_push_overwrite`] [#3954](https://github.com/rust-lang/rust-clippy/pull/3954) +* Move `path_buf_push_overwrite` to the nursery [#4013](https://github.com/rust-lang/rust-clippy/pull/4013) +* Split [`redundant_closure`] into [`redundant_closure`] and [`redundant_closure_for_method_calls`] [#4110](https://github.com/rust-lang/rust-clippy/pull/4101) +* Allow allowing of [`toplevel_ref_arg`] lint [#4007](https://github.com/rust-lang/rust-clippy/pull/4007) +* Fix false negative in [`or_fun_call`] pertaining to nested constructors [#4084](https://github.com/rust-lang/rust-clippy/pull/4084) +* Fix false positive in [`or_fun_call`] pertaining to enum variant constructors [#4018](https://github.com/rust-lang/rust-clippy/pull/4018) +* Fix false positive in [`useless_let_if_seq`] pertaining to interior mutability [#4035](https://github.com/rust-lang/rust-clippy/pull/4035) +* Fix false positive in [`redundant_closure`] pertaining to non-function types [#4008](https://github.com/rust-lang/rust-clippy/pull/4008) +* Fix false positive in [`let_and_return`] pertaining to attributes on `let`s [#4024](https://github.com/rust-lang/rust-clippy/pull/4024) +* Fix false positive in [`module_name_repetitions`] lint pertaining to attributes [#4006](https://github.com/rust-lang/rust-clippy/pull/4006) +* Fix false positive on [`assertions_on_constants`] pertaining to `debug_assert!` [#3989](https://github.com/rust-lang/rust-clippy/pull/3989) +* Improve suggestion in [`map_clone`] to suggest `.copied()` where applicable [#3970](https://github.com/rust-lang/rust-clippy/pull/3970) [#4043](https://github.com/rust-lang/rust-clippy/pull/4043) +* Improve suggestion for [`search_is_some`] [#4049](https://github.com/rust-lang/rust-clippy/pull/4049) +* Improve suggestion applicability for [`naive_bytecount`] [#3984](https://github.com/rust-lang/rust-clippy/pull/3984) +* Improve suggestion applicability for [`while_let_loop`] [#3975](https://github.com/rust-lang/rust-clippy/pull/3975) +* Improve diagnostics for [`too_many_arguments`] [#4053](https://github.com/rust-lang/rust-clippy/pull/4053) +* Improve diagnostics for [`cast_lossless`] [#4021](https://github.com/rust-lang/rust-clippy/pull/4021) +* Deal with macro checks in desugarings better [#4082](https://github.com/rust-lang/rust-clippy/pull/4082) +* Add macro check for [`unnecessary_cast`] [#4026](https://github.com/rust-lang/rust-clippy/pull/4026) +* Remove [`approx_constant`]'s documentation's "Known problems" section. [#4027](https://github.com/rust-lang/rust-clippy/pull/4027) +* Fix ICE in [`suspicious_else_formatting`] [#3960](https://github.com/rust-lang/rust-clippy/pull/3960) +* Fix ICE in [`decimal_literal_representation`] [#3931](https://github.com/rust-lang/rust-clippy/pull/3931) ## Rust 1.35 @@ -234,27 +234,27 @@ Released 2019-05-20 [1fac380..37f5c1e](https://github.com/rust-lang/rust-clippy/compare/1fac380...37f5c1e) - * New lint: [`drop_bounds`] to detect `T: Drop` bounds - * Split [`redundant_closure`] into [`redundant_closure`] and [`redundant_closure_for_method_calls`] [#4110](https://github.com/rust-lang/rust-clippy/pull/4101) - * Rename `cyclomatic_complexity` to [`cognitive_complexity`], start work on making lint more practical for Rust code - * Move [`get_unwrap`] to the restriction category - * Improve suggestions for [`iter_cloned_collect`] - * Improve suggestions for [`cast_lossless`] to suggest suffixed literals - * Fix false positives in [`print_with_newline`] and [`write_with_newline`] pertaining to raw strings - * Fix false positive in [`needless_range_loop`] pertaining to structs without a `.iter()` - * Fix false positive in [`bool_comparison`] pertaining to non-bool types - * Fix false positive in [`redundant_closure`] pertaining to differences in borrows - * Fix false positive in [`option_map_unwrap_or`] on non-copy types - * Fix false positives in [`missing_const_for_fn`] pertaining to macros and trait method impls - * Fix false positive in [`needless_pass_by_value`] pertaining to procedural macros - * Fix false positive in [`needless_continue`] pertaining to loop labels - * Fix false positive for [`boxed_local`] pertaining to arguments moved into closures - * Fix false positive for [`use_self`] in nested functions - * Fix suggestion for [`expect_fun_call`] (https://github.com/rust-lang/rust-clippy/pull/3846) - * Fix suggestion for [`explicit_counter_loop`] to deal with parenthesizing range variables - * Fix suggestion for [`single_char_pattern`] to correctly escape single quotes - * Avoid triggering [`redundant_closure`] in macros - * ICE fixes: [#3805](https://github.com/rust-lang/rust-clippy/pull/3805), [#3772](https://github.com/rust-lang/rust-clippy/pull/3772), [#3741](https://github.com/rust-lang/rust-clippy/pull/3741) +* New lint: [`drop_bounds`] to detect `T: Drop` bounds +* Split [`redundant_closure`] into [`redundant_closure`] and [`redundant_closure_for_method_calls`] [#4110](https://github.com/rust-lang/rust-clippy/pull/4101) +* Rename `cyclomatic_complexity` to [`cognitive_complexity`], start work on making lint more practical for Rust code +* Move [`get_unwrap`] to the restriction category +* Improve suggestions for [`iter_cloned_collect`] +* Improve suggestions for [`cast_lossless`] to suggest suffixed literals +* Fix false positives in [`print_with_newline`] and [`write_with_newline`] pertaining to raw strings +* Fix false positive in [`needless_range_loop`] pertaining to structs without a `.iter()` +* Fix false positive in [`bool_comparison`] pertaining to non-bool types +* Fix false positive in [`redundant_closure`] pertaining to differences in borrows +* Fix false positive in [`option_map_unwrap_or`] on non-copy types +* Fix false positives in [`missing_const_for_fn`] pertaining to macros and trait method impls +* Fix false positive in [`needless_pass_by_value`] pertaining to procedural macros +* Fix false positive in [`needless_continue`] pertaining to loop labels +* Fix false positive for [`boxed_local`] pertaining to arguments moved into closures +* Fix false positive for [`use_self`] in nested functions +* Fix suggestion for [`expect_fun_call`] (https://github.com/rust-lang/rust-clippy/pull/3846) +* Fix suggestion for [`explicit_counter_loop`] to deal with parenthesizing range variables +* Fix suggestion for [`single_char_pattern`] to correctly escape single quotes +* Avoid triggering [`redundant_closure`] in macros +* ICE fixes: [#3805](https://github.com/rust-lang/rust-clippy/pull/3805), [#3772](https://github.com/rust-lang/rust-clippy/pull/3772), [#3741](https://github.com/rust-lang/rust-clippy/pull/3741) ## Rust 1.34 @@ -551,7 +551,7 @@ Released 2018-09-13 ## 0.0.181 * Rustup to *rustc 1.25.0-nightly (97520ccb1 2018-01-21)* * New lints: [`else_if_without_else`], [`option_option`], [`unit_arg`], [`unnecessary_fold`] -* Removed [`unit_expr`] +* Removed `unit_expr` * Various false positive fixes for [`needless_pass_by_value`] ## 0.0.180 @@ -597,11 +597,13 @@ Released 2018-09-13 ## 0.0.167 * Rustup to *rustc 1.23.0-nightly (90ef3372e 2017-10-29)* -* New lints: [`const_static_lifetime`], [`erasing_op`], [`fallible_impl_from`], [`println_empty_string`], [`useless_asref`] +* New lints: `const_static_lifetime`, [`erasing_op`], [`fallible_impl_from`], [`println_empty_string`], [`useless_asref`] ## 0.0.166 * Rustup to *rustc 1.22.0-nightly (b7960878b 2017-10-18)* -* New lints: [`explicit_write`], [`identity_conversion`], [`implicit_hasher`], [`invalid_ref`], [`option_map_or_none`], [`range_minus_one`], [`range_plus_one`], [`transmute_int_to_bool`], [`transmute_int_to_char`], [`transmute_int_to_float`] +* New lints: [`explicit_write`], [`identity_conversion`], [`implicit_hasher`], [`invalid_ref`], [`option_map_or_none`], + [`range_minus_one`], [`range_plus_one`], [`transmute_int_to_bool`], [`transmute_int_to_char`], + [`transmute_int_to_float`] ## 0.0.165 * Rust upgrade to rustc 1.22.0-nightly (0e6f4cf51 2017-09-27) @@ -636,7 +638,7 @@ Released 2018-09-13 ## 0.0.157 - 2017-09-04 * Update to *rustc 1.22.0-nightly (981ce7d8d 2017-09-03)* -* New lint: [`unit_expr`] +* New lint: `unit_expr` ## 0.0.156 - 2017-09-03 * Update to *rustc 1.22.0-nightly (744dd6c1d 2017-09-02)* @@ -884,7 +886,7 @@ Released 2018-09-13 lint groups: [`filter_next`], [`for_loop_over_option`], [`for_loop_over_result`] and [`match_overlapping_arm`]. You should now be able to `#[allow/deny]` them individually and they are available directly - through [`cargo clippy`]. + through `cargo clippy`. ## 0.0.87 — 2016-08-31 * Rustup to *rustc 1.13.0-nightly (eac41469d 2016-08-30)* @@ -897,7 +899,7 @@ Released 2018-09-13 ## 0.0.85 — 2016-08-19 * Fix ICE with [`useless_attribute`] -* [`useless_attribute`] ignores [`unused_imports`] on `use` statements +* [`useless_attribute`] ignores `unused_imports` on `use` statements ## 0.0.84 — 2016-08-18 * Rustup to *rustc 1.13.0-nightly (aef6971ca 2016-08-17)* @@ -936,7 +938,7 @@ Released 2018-09-13 ## 0.0.77 — 2016-06-21 * Rustup to *rustc 1.11.0-nightly (5522e678b 2016-06-20)* -* New lints: [`stutter`] and [`iter_nth`] +* New lints: `stutter` and [`iter_nth`] ## 0.0.76 — 2016-06-10 * Rustup to *rustc 1.11.0-nightly (7d2f75a95 2016-06-09)* @@ -1056,6 +1058,7 @@ Released 2018-09-13 [pull3665]: https://github.com/rust-lang/rust-clippy/pull/3665 [adding_lints]: https://github.com/rust-lang/rust-clippy/blob/master/doc/adding_lints.md + [`absurd_extreme_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#absurd_extreme_comparisons [`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index d70b2b52aca1..dec13e44a17f 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -6,35 +6,65 @@ A version of this document [can be found online](https://www.rust-lang.org/condu **Contact**: [rust-mods@rust-lang.org](mailto:rust-mods@rust-lang.org) -* We are committed to providing a friendly, safe and welcoming environment for all, regardless of level of experience, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, nationality, or other similar characteristic. -* On IRC, please avoid using overtly sexual nicknames or other nicknames that might detract from a friendly, safe and welcoming environment for all. +* We are committed to providing a friendly, safe and welcoming environment for all, regardless of level of experience, + gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, + religion, nationality, or other similar characteristic. +* On IRC, please avoid using overtly sexual nicknames or other nicknames that might detract from a friendly, safe and + welcoming environment for all. * Please be kind and courteous. There's no need to be mean or rude. -* Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer. -* Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and see how it works. -* We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behavior. We interpret the term "harassment" as including the definition in the Citizen Code of Conduct; if you have any lack of clarity about what might be included in that concept, please read their definition. In particular, we don't tolerate behavior that excludes people in socially marginalized groups. -* Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one of the channel ops or any of the [Rust moderation team][mod_team] immediately. Whether you're a regular contributor or a newcomer, we care about making this community a safe place for you and we've got your back. +* Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and + numerous costs. There is seldom a right answer. +* Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and + see how it works. +* We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behavior. We + interpret the term "harassment" as including the definition in the Citizen + Code of Conduct; if you have any lack of clarity about what might be included in that concept, please read their + definition. In particular, we don't tolerate behavior that excludes people in socially marginalized groups. +* Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or + made uncomfortable by a community member, please contact one of the channel ops or any of the [Rust moderation + team][mod_team] immediately. Whether you're a regular contributor or a newcomer, we care about making this community a + safe place for you and we've got your back. * Likewise any spamming, trolling, flaming, baiting or other attention-stealing behavior is not welcome. ## Moderation -These are the policies for upholding our community's standards of conduct. If you feel that a thread needs moderation, please contact the [Rust moderation team][mod_team]. +These are the policies for upholding our community's standards of conduct. If you feel that a thread needs moderation, +please contact the [Rust moderation team][mod_team]. -1. Remarks that violate the Rust standards of conduct, including hateful, hurtful, oppressive, or exclusionary remarks, are not allowed. (Cursing is allowed, but never targeting another user, and never in a hateful manner.) +1. Remarks that violate the Rust standards of conduct, including hateful, hurtful, oppressive, or exclusionary remarks, + are not allowed. (Cursing is allowed, but never targeting another user, and never in a hateful manner.) 2. Remarks that moderators find inappropriate, whether listed in the code of conduct or not, are also not allowed. 3. Moderators will first respond to such remarks with a warning. 4. If the warning is unheeded, the user will be "kicked," i.e., kicked out of the communication channel to cool off. 5. If the user comes back and continues to make trouble, they will be banned, i.e., indefinitely excluded. -6. Moderators may choose at their discretion to un-ban the user if it was a first offense and they offer the offended party a genuine apology. -7. If a moderator bans someone and you think it was unjustified, please take it up with that moderator, or with a different moderator, **in private**. Complaints about bans in-channel are not allowed. -8. Moderators are held to a higher standard than other community members. If a moderator creates an inappropriate situation, they should expect less leeway than others. +6. Moderators may choose at their discretion to un-ban the user if it was a first offense and they offer the offended + party a genuine apology. +7. If a moderator bans someone and you think it was unjustified, please take it up with that moderator, or with a + different moderator, **in private**. Complaints about bans in-channel are not allowed. +8. Moderators are held to a higher standard than other community members. If a moderator creates an inappropriate + situation, they should expect less leeway than others. -In the Rust community we strive to go the extra step to look out for each other. Don't just aim to be technically unimpeachable, try to be your best self. In particular, avoid flirting with offensive or sensitive issues, particularly if they're off-topic; this all too often leads to unnecessary fights, hurt feelings, and damaged trust; worse, it can drive people away from the community entirely. +In the Rust community we strive to go the extra step to look out for each other. Don't just aim to be technically +unimpeachable, try to be your best self. In particular, avoid flirting with offensive or sensitive issues, particularly +if they're off-topic; this all too often leads to unnecessary fights, hurt feelings, and damaged trust; worse, it can +drive people away from the community entirely. -And if someone takes issue with something you said or did, resist the urge to be defensive. Just stop doing what it was they complained about and apologize. Even if you feel you were misinterpreted or unfairly accused, chances are good there was something you could've communicated better — remember that it's your responsibility to make your fellow Rustaceans comfortable. Everyone wants to get along and we are all here first and foremost because we want to talk about cool technology. You will find that people will be eager to assume good intent and forgive as long as you earn their trust. +And if someone takes issue with something you said or did, resist the urge to be defensive. Just stop doing what it was +they complained about and apologize. Even if you feel you were misinterpreted or unfairly accused, chances are good +there was something you could've communicated better — remember that it's your responsibility to make your fellow +Rustaceans comfortable. Everyone wants to get along and we are all here first and foremost because we want to talk about +cool technology. You will find that people will be eager to assume good intent and forgive as long as you earn their +trust. -The enforcement policies listed above apply to all official Rust venues; including official IRC channels (#rust, #rust-internals, #rust-tools, #rust-libs, #rustc, #rust-beginners, #rust-docs, #rust-community, #rust-lang, and #cargo); GitHub repositories under rust-lang, rust-lang-nursery, and rust-lang-deprecated; and all forums under rust-lang.org (users.rust-lang.org, internals.rust-lang.org). For other projects adopting the Rust Code of Conduct, please contact the maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion. +The enforcement policies listed above apply to all official Rust venues; including official IRC channels (#rust, +#rust-internals, #rust-tools, #rust-libs, #rustc, #rust-beginners, #rust-docs, #rust-community, #rust-lang, and #cargo); +GitHub repositories under rust-lang, rust-lang-nursery, and rust-lang-deprecated; and all forums under rust-lang.org +(users.rust-lang.org, internals.rust-lang.org). For other projects adopting the Rust Code of Conduct, please contact the +maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider +explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion. -*Adapted from the [Node.js Policy on Trolling](http://blog.izs.me/post/30036893703/policy-on-trolling) as well as the [Contributor Covenant v1.3.0](https://www.contributor-covenant.org/version/1/3/0/).* +*Adapted from the [Node.js Policy on Trolling](http://blog.izs.me/post/30036893703/policy-on-trolling) as well as the +[Contributor Covenant v1.3.0](https://www.contributor-covenant.org/version/1/3/0/).* [mod_team]: https://www.rust-lang.org/team.html#Moderation-team diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 68eb64c94b6d..4777f2fabeb2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,12 +2,14 @@ Hello fellow Rustacean! Great to see your interest in compiler internals and lints! -**First**: if you're unsure or afraid of _anything_, just ask or submit the issue or pull request anyway. You won't be yelled at for giving it your best effort. The worst that can happen is that you'll be politely asked to change something. We appreciate any sort of contributions, and don't want a wall of rules to get in the way of that. +**First**: if you're unsure or afraid of _anything_, just ask or submit the issue or pull request anyway. You won't be +yelled at for giving it your best effort. The worst that can happen is that you'll be politely asked to change +something. We appreciate any sort of contributions, and don't want a wall of rules to get in the way of that. -Clippy welcomes contributions from everyone. There are many ways to contribute to Clippy and the following document explains how -you can contribute and how to get started. -If you have any questions about contributing or need help with anything, feel free to ask questions on issues or -visit the `#clippy` IRC channel on `irc.mozilla.org` or meet us in `#clippy` on [Discord](https://discord.gg/rust-lang). +Clippy welcomes contributions from everyone. There are many ways to contribute to Clippy and the following document +explains how you can contribute and how to get started. If you have any questions about contributing or need help with +anything, feel free to ask questions on issues or visit the `#clippy` IRC channel on `irc.mozilla.org` or meet us in +`#clippy` on [Discord](https://discord.gg/rust-lang). All contributors are expected to follow the [Rust Code of Conduct](http://www.rust-lang.org/conduct.html). @@ -49,12 +51,12 @@ matching of the syntax tree structure, and are generally easier than [`T-middle`](https://github.com/rust-lang/rust-clippy/labels/T-middle) issues, which involve types and resolved paths. -[`T-AST`](https://github.com/rust-lang/rust-clippy/labels/T-AST) issues will generally need you to match against a predefined syntax structure. To figure out -how this syntax structure is encoded in the AST, it is recommended to run `rustc -Z ast-json` on an -example of the structure and compare with the -[nodes in the AST docs](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/ast). Usually -the lint will end up to be a nested series of matches and ifs, -[like so](https://github.com/rust-lang/rust-clippy/blob/de5ccdfab68a5e37689f3c950ed1532ba9d652a0/src/misc.rs#L34). +[`T-AST`](https://github.com/rust-lang/rust-clippy/labels/T-AST) issues will generally need you to match against a +predefined syntax structure. To figure out how this syntax structure is encoded in the AST, it is recommended to run +`rustc -Z ast-json` on an example of the structure and compare with the [nodes in the AST +docs](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/ast). Usually the lint will end up to be a nested series of +matches and ifs, [like +so](https://github.com/rust-lang/rust-clippy/blob/de5ccdfab68a5e37689f3c950ed1532ba9d652a0/src/misc.rs#L34). [`E-medium`](https://github.com/rust-lang/rust-clippy/labels/E-medium) issues are generally pretty easy too, though it's recommended you work on an E-easy issue first. They are mostly classified @@ -68,9 +70,9 @@ an AST expression). `match_def_path()` in Clippy's `utils` module can also be us ## Writing code -Have a look at the [docs for writing lints](doc/adding_lints.md) for more details. [Llogiq's blog post on lints](https://llogiq.github.io/2015/06/04/workflows.html) is also a nice primer -to lint-writing, though it does get into advanced stuff and may be a bit -outdated. +Have a look at the [docs for writing lints](doc/adding_lints.md) for more details. [Llogiq's blog post on +lints](https://llogiq.github.io/2015/06/04/workflows.html) is also a nice primer to lint-writing, though it does get +into advanced stuff and may be a bit outdated. If you want to add a new lint or change existing ones apart from bugfixing, it's also a good idea to give the [stability guarantees][rfc_stability] and @@ -79,9 +81,11 @@ quick read. ## How Clippy works -Clippy is a [rustc compiler plugin][compiler_plugin]. The main entry point is at [`src/lib.rs`][main_entry]. In there, the lint registration is delegated to the [`clippy_lints`][lint_crate] crate. +Clippy is a [rustc compiler plugin][compiler_plugin]. The main entry point is at [`src/lib.rs`][main_entry]. In there, +the lint registration is delegated to the [`clippy_lints`][lint_crate] crate. -[`clippy_lints/src/lib.rs`][lint_crate_entry] imports all the different lint modules and registers them with the rustc plugin registry. For example, the [`else_if_without_else`][else_if_without_else] lint is registered like this: +[`clippy_lints/src/lib.rs`][lint_crate_entry] imports all the different lint modules and registers them with the rustc +plugin registry. For example, the [`else_if_without_else`][else_if_without_else] lint is registered like this: ```rust // ./clippy_lints/src/lib.rs @@ -103,9 +107,12 @@ pub fn register_plugins(reg: &mut rustc_driver::plugin::Registry) { } ``` -The [`plugin::PluginRegistry`][plugin_registry] provides two methods to register lints: [register_early_lint_pass][reg_early_lint_pass] and [register_late_lint_pass][reg_late_lint_pass]. -Both take an object that implements an [`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass] respectively. This is done in every single lint. -It's worth noting that the majority of `clippy_lints/src/lib.rs` is autogenerated by `cargo dev update_lints` and you don't have to add anything by hand. When you are writing your own lint, you can use that script to save you some time. +The [`plugin::PluginRegistry`][plugin_registry] provides two methods to register lints: +[register_early_lint_pass][reg_early_lint_pass] and [register_late_lint_pass][reg_late_lint_pass]. Both take an object +that implements an [`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass] respectively. This is done in +every single lint. It's worth noting that the majority of `clippy_lints/src/lib.rs` is autogenerated by `cargo dev +update_lints` and you don't have to add anything by hand. When you are writing your own lint, you can use that script to +save you some time. ```rust // ./clippy_lints/src/else_if_without_else.rs @@ -123,18 +130,25 @@ impl EarlyLintPass for ElseIfWithoutElse { } ``` -The difference between `EarlyLintPass` and `LateLintPass` is that the methods of the `EarlyLintPass` trait only provide AST information. The methods of the `LateLintPass` trait are executed after type checking and contain type information via the `LateContext` parameter. +The difference between `EarlyLintPass` and `LateLintPass` is that the methods of the `EarlyLintPass` trait only provide +AST information. The methods of the `LateLintPass` trait are executed after type checking and contain type information +via the `LateContext` parameter. -That's why the `else_if_without_else` example uses the `register_early_lint_pass` function. Because the [actual lint logic][else_if_without_else] does not depend on any type information. +That's why the `else_if_without_else` example uses the `register_early_lint_pass` function. Because the [actual lint +logic][else_if_without_else] does not depend on any type information. ## Fixing build failures caused by Rust -Clippy will sometimes fail to build from source because building it depends on unstable internal Rust features. Most of the times we have to adapt to the changes and only very rarely there's an actual bug in Rust. Fixing build failures caused by Rust updates, can be a good way to learn about Rust internals. +Clippy will sometimes fail to build from source because building it depends on unstable internal Rust features. Most of +the times we have to adapt to the changes and only very rarely there's an actual bug in Rust. Fixing build failures +caused by Rust updates, can be a good way to learn about Rust internals. -In order to find out why Clippy does not work properly with a new Rust commit, you can use the [rust-toolstate commit history][toolstate_commit_history]. -You will then have to look for the last commit that contains `test-pass -> build-fail` or `test-pass` -> `test-fail` for the `clippy-driver` component. [Here][toolstate_commit] is an example. +In order to find out why Clippy does not work properly with a new Rust commit, you can use the [rust-toolstate commit +history][toolstate_commit_history]. You will then have to look for the last commit that contains `test-pass -> +build-fail` or `test-pass` -> `test-fail` for the `clippy-driver` component. [Here][toolstate_commit] is an example. -The commit message contains a link to the PR. The PRs are usually small enough to discover the breaking API change and if they are bigger, they likely include some discussion that may help you to fix Clippy. +The commit message contains a link to the PR. The PRs are usually small enough to discover the breaking API change and +if they are bigger, they likely include some discussion that may help you to fix Clippy. To check if Clippy is available for a specific target platform, you can check the [rustup component history][rustup_component_history]. diff --git a/README.md b/README.md index fd7f33f91d51..af2331fa5331 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,9 @@ Only the following of those categories are enabled by default: Other categories need to be enabled in order for their lints to be executed. -The [lint list](https://rust-lang.github.io/rust-clippy/master/index.html) also contains "restriction lints", which are for things which are usually not considered "bad", but may be useful to turn on in specific cases. These should be used very selectively, if at all. +The [lint list](https://rust-lang.github.io/rust-clippy/master/index.html) also contains "restriction lints", which are +for things which are usually not considered "bad", but may be useful to turn on in specific cases. These should be used +very selectively, if at all. Table of contents: @@ -140,15 +142,16 @@ line. (You can swap `clippy::all` with the specific lint category you are target ## Configuration -Some lints can be configured in a TOML file named `clippy.toml` or `.clippy.toml`. It contains a basic `variable = value` mapping eg. +Some lints can be configured in a TOML file named `clippy.toml` or `.clippy.toml`. It contains a basic `variable = +value` mapping eg. ```toml blacklisted-names = ["toto", "tata", "titi"] cognitive-complexity-threshold = 30 ``` -See the [list of lints](https://rust-lang.github.io/rust-clippy/master/index.html) for more information about which lints can be configured and the -meaning of the variables. +See the [list of lints](https://rust-lang.github.io/rust-clippy/master/index.html) for more information about which +lints can be configured and the meaning of the variables. To deactivate the “for further information visit *lint-link*” message you can define the `CLIPPY_DISABLE_DOCS_LINKS` environment variable. @@ -169,7 +172,10 @@ You can add options to your code to `allow`/`warn`/`deny` Clippy lints: Note: `deny` produces errors instead of warnings. -If you do not want to include your lint levels in your code, you can globally enable/disable lints by passing extra flags to Clippy during the run: `cargo clippy -- -A clippy::lint_name` will run Clippy with `lint_name` disabled and `cargo clippy -- -W clippy::lint_name` will run it with that enabled. This also works with lint groups. For example you can run Clippy with warnings for all lints enabled: `cargo clippy -- -W clippy::pedantic` +If you do not want to include your lint levels in your code, you can globally enable/disable lints by passing extra +flags to Clippy during the run: `cargo clippy -- -A clippy::lint_name` will run Clippy with `lint_name` disabled and +`cargo clippy -- -W clippy::lint_name` will run it with that enabled. This also works with lint groups. For example you +can run Clippy with warnings for all lints enabled: `cargo clippy -- -W clippy::pedantic` ## Contributing diff --git a/clippy_dummy/PUBLISH.md b/clippy_dummy/PUBLISH.md index 535f11bd2ee4..8e420ec959a2 100644 --- a/clippy_dummy/PUBLISH.md +++ b/clippy_dummy/PUBLISH.md @@ -1,4 +1,6 @@ -This is a dummy crate to publish to crates.io. It primarily exists to ensure that folks trying to install clippy from crates.io get redirected to the `rustup` technique. +This is a dummy crate to publish to crates.io. It primarily exists to ensure +that folks trying to install clippy from crates.io get redirected to the +`rustup` technique. -Before publishing, be sure to rename `clippy_dummy` to `clippy` in `Cargo.toml`, it has a different name to avoid workspace issues. - \ No newline at end of file +Before publishing, be sure to rename `clippy_dummy` to `clippy` in `Cargo.toml`, +it has a different name to avoid workspace issues. diff --git a/doc/adding_lints.md b/doc/adding_lints.md index e1f4ce016c5c..cc4b5f7d1623 100644 --- a/doc/adding_lints.md +++ b/doc/adding_lints.md @@ -167,12 +167,12 @@ declare_clippy_lint! { ``` * The section of lines prefixed with `///` constitutes the lint documentation -section. This is the default documentation style and will be displayed at -https://rust-lang.github.io/rust-clippy/master/index.html. + section. This is the default documentation style and will be displayed at + https://rust-lang.github.io/rust-clippy/master/index.html. * `FOO_FUNCTIONS` is the name of our lint. Be sure to follow the [lint naming -guidelines][lint_naming] here when naming your lint. In short, the name should -state the thing that is being checked for and read well when used with -`allow`/`warn`/`deny`. + guidelines][lint_naming] here when naming your lint. In short, the name should + state the thing that is being checked for and read well when used with + `allow`/`warn`/`deny`. * `pedantic` sets the lint level to `Allow`. The exact mapping can be found [here][category_level_mapping] * The last part should be a text that explains what exactly is wrong with the @@ -443,7 +443,6 @@ don't hesitate to ask on Discord, IRC or in the issue/PR. [lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints [category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/bd23cb89ec0ea63403a17d3fc5e50c88e38dd54f/clippy_lints/src/lib.rs#L43 [declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/a71acac1da7eaf667ab90a1d65d10e5cc4b80191/clippy_lints/src/lib.rs#L39 -[compilation_stages]: https://rust-lang.github.io/rustc-guide/high-level-overview.html#the-main-stages-of-compilation [check_fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/trait.EarlyLintPass.html#method.check_fn [early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/trait.EarlyLintPass.html [late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/trait.LateLintPass.html diff --git a/etc/relicense/RELICENSE_DOCUMENTATION.md b/etc/relicense/RELICENSE_DOCUMENTATION.md index 847e66e65e35..fcd7abbf3f16 100644 --- a/etc/relicense/RELICENSE_DOCUMENTATION.md +++ b/etc/relicense/RELICENSE_DOCUMENTATION.md @@ -1,36 +1,69 @@ -This repository was previously licensed under MPL-2.0, however in #3093 ([archive](http://web.archive.org/web/20181005185227/https://github.com/rust-lang-nursery/rust-clippy/issues/3093), [screenshot](https://user-images.githubusercontent.com/1617736/46573505-5b856880-c94b-11e8-9a14-981c889b4981.png)) we relicensed it to the Rust license (dual licensed as Apache v2 / MIT) +This repository was previously licensed under MPL-2.0, however in #3093 +([archive](http://web.archive.org/web/20181005185227/https://github.com/rust-lang-nursery/rust-clippy/issues/3093), +[screenshot](https://user-images.githubusercontent.com/1617736/46573505-5b856880-c94b-11e8-9a14-981c889b4981.png)) we +relicensed it to the Rust license (dual licensed as Apache v2 / MIT) At the time, the contributors were those listed in contributors.txt. -We opened a bunch of issues asking for an explicit relicensing approval. Screenshots of all these issues at the time of relicensing are archived on GitHub. We also have saved Wayback Machine copies of these: +We opened a bunch of issues asking for an explicit relicensing approval. Screenshots of all these issues at the time of +relicensing are archived on GitHub. We also have saved Wayback Machine copies of these: - - #3094 ([archive](http://web.archive.org/web/20181005191247/https://github.com/rust-lang-nursery/rust-clippy/issues/3094), [screenshot](https://user-images.githubusercontent.com/1617736/46573506-5b856880-c94b-11e8-8a44-51cb40bc16ee.png)) - - #3095 ([archive](http://web.archive.org/web/20181005184416/https://github.com/rust-lang-nursery/rust-clippy/issues/3095), [screenshot](https://user-images.githubusercontent.com/1617736/46573507-5c1dff00-c94b-11e8-912a-4bd6b5f838f5.png)) - - #3096 ([archive](http://web.archive.org/web/20181005184802/https://github.com/rust-lang-nursery/rust-clippy/issues/3096), [screenshot](https://user-images.githubusercontent.com/1617736/46573508-5c1dff00-c94b-11e8-9425-2464f7260ff0.png)) - - #3097 ([archive](http://web.archive.org/web/20181005184821/https://github.com/rust-lang-nursery/rust-clippy/issues/3097), [screenshot](https://user-images.githubusercontent.com/1617736/46573509-5c1dff00-c94b-11e8-8ba2-53f687984fe7.png)) - - #3098 ([archive](http://web.archive.org/web/20181005184900/https://github.com/rust-lang-nursery/rust-clippy/issues/3098), [screenshot](https://user-images.githubusercontent.com/1617736/46573510-5c1dff00-c94b-11e8-8f64-371698401c60.png)) - - #3099 ([archive](http://web.archive.org/web/20181005184901/https://github.com/rust-lang-nursery/rust-clippy/issues/3099), [screenshot](https://user-images.githubusercontent.com/1617736/46573511-5c1dff00-c94b-11e8-8e20-7d0eeb392b95.png)) - - #3100 ([archive](http://web.archive.org/web/20181005184901/https://github.com/rust-lang-nursery/rust-clippy/issues/3100), [screenshot](https://user-images.githubusercontent.com/1617736/46573512-5c1dff00-c94b-11e8-8a13-7d758ed3563d.png)) - - #3230 ([archive](http://web.archive.org/web/20181005184903/https://github.com/rust-lang-nursery/rust-clippy/issues/3230), [screenshot](https://user-images.githubusercontent.com/1617736/46573513-5cb69580-c94b-11e8-86b1-14ce82741e5c.png)) +- #3094 + ([archive](http://web.archive.org/web/20181005191247/https://github.com/rust-lang-nursery/rust-clippy/issues/3094), + [screenshot](https://user-images.githubusercontent.com/1617736/46573506-5b856880-c94b-11e8-8a44-51cb40bc16ee.png)) +- #3095 + ([archive](http://web.archive.org/web/20181005184416/https://github.com/rust-lang-nursery/rust-clippy/issues/3095), + [screenshot](https://user-images.githubusercontent.com/1617736/46573507-5c1dff00-c94b-11e8-912a-4bd6b5f838f5.png)) +- #3096 + ([archive](http://web.archive.org/web/20181005184802/https://github.com/rust-lang-nursery/rust-clippy/issues/3096), + [screenshot](https://user-images.githubusercontent.com/1617736/46573508-5c1dff00-c94b-11e8-9425-2464f7260ff0.png)) +- #3097 + ([archive](http://web.archive.org/web/20181005184821/https://github.com/rust-lang-nursery/rust-clippy/issues/3097), + [screenshot](https://user-images.githubusercontent.com/1617736/46573509-5c1dff00-c94b-11e8-8ba2-53f687984fe7.png)) +- #3098 + ([archive](http://web.archive.org/web/20181005184900/https://github.com/rust-lang-nursery/rust-clippy/issues/3098), + [screenshot](https://user-images.githubusercontent.com/1617736/46573510-5c1dff00-c94b-11e8-8f64-371698401c60.png)) +- #3099 + ([archive](http://web.archive.org/web/20181005184901/https://github.com/rust-lang-nursery/rust-clippy/issues/3099), + [screenshot](https://user-images.githubusercontent.com/1617736/46573511-5c1dff00-c94b-11e8-8e20-7d0eeb392b95.png)) +- #3100 + ([archive](http://web.archive.org/web/20181005184901/https://github.com/rust-lang-nursery/rust-clippy/issues/3100), + [screenshot](https://user-images.githubusercontent.com/1617736/46573512-5c1dff00-c94b-11e8-8a13-7d758ed3563d.png)) +- #3230 + ([archive](http://web.archive.org/web/20181005184903/https://github.com/rust-lang-nursery/rust-clippy/issues/3230), + [screenshot](https://user-images.githubusercontent.com/1617736/46573513-5cb69580-c94b-11e8-86b1-14ce82741e5c.png)) The usernames of commenters on these issues can be found in relicense_comments.txt There are a couple people in relicense_comments.txt who are not found in contributors.txt: - - @EpocSquadron has [made minor text contributions to the README](https://github.com/rust-lang/rust-clippy/commits?author=EpocSquadron) which have since been overwritten, and doesn't count - - @JayKickliter [agreed to the relicense on their pull request](https://github.com/rust-lang/rust-clippy/pull/3195#issuecomment-423781016) ([archive](https://web.archive.org/web/20181005190730/https://github.com/rust-lang/rust-clippy/pull/3195), [screenshot](https://user-images.githubusercontent.com/1617736/46573514-5cb69580-c94b-11e8-8ffb-05a5bd02e2cc.png) -) - - @sanmai-NL's [contribution](https://github.com/rust-lang/rust-clippy/commits?author=sanmai-NL) is a minor one-word addition which doesn't count for copyright assignment - - @zmt00's [contributions](https://github.com/rust-lang/rust-clippy/commits?author=zmt00) are minor typo fixes and don't count - - @VKlayd has [nonminor contributions](https://github.com/rust-lang/rust-clippy/commits?author=VKlayd) which we rewrote (see below) - - @wartman4404 has [nonminor contributions](https://github.com/rust-lang/rust-clippy/commits?author=wartman4404) which we rewrote (see below) +- @EpocSquadron has [made minor text contributions to the + README](https://github.com/rust-lang/rust-clippy/commits?author=EpocSquadron) which have since been overwritten, and + doesn't count +- @JayKickliter [agreed to the relicense on their pull + request](https://github.com/rust-lang/rust-clippy/pull/3195#issuecomment-423781016) + ([archive](https://web.archive.org/web/20181005190730/https://github.com/rust-lang/rust-clippy/pull/3195), + [screenshot](https://user-images.githubusercontent.com/1617736/46573514-5cb69580-c94b-11e8-8ffb-05a5bd02e2cc.png) +- @sanmai-NL's [contribution](https://github.com/rust-lang/rust-clippy/commits?author=sanmai-NL) is a minor one-word + addition which doesn't count for copyright assignment +- @zmt00's [contributions](https://github.com/rust-lang/rust-clippy/commits?author=zmt00) are minor typo fixes and don't + count +- @VKlayd has [nonminor contributions](https://github.com/rust-lang/rust-clippy/commits?author=VKlayd) which we rewrote + (see below) +- @wartman4404 has [nonminor contributions](https://github.com/rust-lang/rust-clippy/commits?author=wartman4404) which + we rewrote (see below) -Two of these contributors had nonminor contributions (#2184, #427) requiring a rewrite, carried out in #3251 ([archive](http://web.archive.org/web/20181005192411/https://github.com/rust-lang-nursery/rust-clippy/pull/3251), [screenshot](https://user-images.githubusercontent.com/1617736/46573515-5cb69580-c94b-11e8-86e5-b456452121b2.png) -) -First, I (Manishearth) removed the lints they had added. I then documented at a high level what the lints did in #3251, asking for co-maintainers who had not seen the code for the lints to rewrite them. #2814 was rewritten by @phansch, and #427 was rewritten by @oli-obk, who did not recall having previously seen the code they were rewriting. +Two of these contributors had nonminor contributions (#2184, #427) requiring a rewrite, carried out in #3251 +([archive](http://web.archive.org/web/20181005192411/https://github.com/rust-lang-nursery/rust-clippy/pull/3251), +[screenshot](https://user-images.githubusercontent.com/1617736/46573515-5cb69580-c94b-11e8-86e5-b456452121b2.png)) + +First, I (Manishearth) removed the lints they had added. I then documented at a high level what the lints did in #3251, +asking for co-maintainers who had not seen the code for the lints to rewrite them. #2814 was rewritten by @phansch, and +#427 was rewritten by @oli-obk, who did not recall having previously seen the code they were rewriting. ------ -Since this document was written, @JayKickliter and @sanmai-ML added their consent in #3230 ([archive](http://web.archive.org/web/20181006171926/https://github.com/rust-lang-nursery/rust-clippy/issues/3230)) +Since this document was written, @JayKickliter and @sanmai-ML added their consent in #3230 +([archive](http://web.archive.org/web/20181006171926/https://github.com/rust-lang-nursery/rust-clippy/issues/3230)) From d14ee8a4b1f41121d799c3f5b868d916ac0f24bd Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 21 Jan 2020 18:43:57 +0100 Subject: [PATCH 043/243] Add Clippy Test (bors) to GHA --- .github/workflows/clippy_bors.yml | 146 ++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 .github/workflows/clippy_bors.yml diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml new file mode 100644 index 000000000000..6a6d58410f95 --- /dev/null +++ b/.github/workflows/clippy_bors.yml @@ -0,0 +1,146 @@ +name: Clippy Test (bors) + +on: + push: + branches: [auto, try] + # Don't run Clippy tests, when only textfiles were modified + paths-ignore: + - 'COPYRIGHT' + - 'LICENSE-*' + - '**.md' + - '**.txt' + +env: + RUST_BACKTRACE: 1 + CARGO_TARGET_DIR: '${{ github.workspace }}/target' + GHA_CI: 1 + +jobs: + base: + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + host: [x86_64-unknown-linux-gnu, i686-unknown-linux-gnu, x86_64-apple-darwin, x86_64-pc-windows-msvc] + exclude: + - os: ubuntu-latest + host: x86_64-apple-darwin + - os: ubuntu-latest + host: x86_64-pc-windows-msvc + - os: macos-latest + host: x86_64-unknown-linux-gnu + - os: macos-latest + host: i686-unknown-linux-gnu + - os: macos-latest + host: x86_64-pc-windows-msvc + - os: windows-latest + host: x86_64-unknown-linux-gnu + - os: windows-latest + host: i686-unknown-linux-gnu + - os: windows-latest + host: x86_64-apple-darwin + + runs-on: ${{ matrix.os }} + + steps: + - name: Install dependencies (Linux-i686) + run: | + sudo dpkg --add-architecture i386 + sudo apt-get update + sudo apt-get install gcc-multilib libssl-dev:i386 libgit2-dev:i386 + if: matrix.host == 'i686-unknown-linux-gnu' + - name: rust-toolchain + uses: actions-rs/toolchain@v1.0.3 + with: + toolchain: nightly + target: ${{ matrix.host }} + profile: minimal + - name: Cache cargo dir + uses: actions/cache@v1 + with: + path: ~/.cargo + key: ${{ runner.os }}-${{ matrix.host }} + - name: Checkout + uses: actions/checkout@v2.0.0 + - name: Master Toolchain Setup + run: bash setup-toolchain.sh + env: + HOST_TOOLCHAIN: ${{ matrix.host }} + shell: bash + + - name: Set LD_LIBRARY_PATH (Linux) + if: runner.os == 'Linux' + run: | + SYSROOT=$(rustc --print sysroot) + echo "::set-env name=LD_LIBRARY_PATH::${SYSROOT}/lib${LD_LIBRARY_PATH+:${LD_LIBRARY_PATH}}" + - name: Link rustc dylib (MacOS) + if: runner.os == 'macOS' + run: | + SYSROOT=$(rustc --print sysroot) + sudo mkdir -p /usr/local/lib + sudo find "${SYSROOT}/lib" -maxdepth 1 -name '*dylib' -exec ln -s {} /usr/local/lib \; + - name: Set PATH (Windows) + if: runner.os == 'Windows' + run: | + $sysroot = rustc --print sysroot + $env:PATH += ';' + $sysroot + '\bin' + echo "::set-env name=PATH::$env:PATH" + - name: Build + run: cargo build --features deny-warnings + shell: bash + - name: Test + run: cargo test --features deny-warnings + shell: bash + - name: Test clippy_lints + run: cargo test --features deny-warnings + shell: bash + working-directory: clippy_lints + - name: Test rustc_tools_util + run: cargo test --features deny-warnings + shell: bash + working-directory: rustc_tools_util + - name: Test clippy_dev + run: cargo test --features deny-warnings + shell: bash + working-directory: clippy_dev + - name: Test cargo-clippy + run: ../target/debug/cargo-clippy + shell: bash + working-directory: clippy_workspace_tests + - name: Test clippy-driver + run: | + ( + set -ex + # Check sysroot handling + sysroot=$(./target/debug/clippy-driver --print sysroot) + test "$sysroot" = "$(rustc --print sysroot)" + + if [[ ${{ runner.os }} == "Windows" ]]; then + desired_sysroot=C:/tmp + else + desired_sysroot=/tmp + fi + sysroot=$(./target/debug/clippy-driver --sysroot $desired_sysroot --print sysroot) + test "$sysroot" = $desired_sysroot + + sysroot=$(SYSROOT=$desired_sysroot ./target/debug/clippy-driver --print sysroot) + test "$sysroot" = $desired_sysroot + + # Make sure this isn't set - clippy-driver should cope without it + unset CARGO_MANIFEST_DIR + + # Run a lint and make sure it produces the expected output. It's also expected to exit with code 1 + # FIXME: How to match the clippy invocation in compile-test.rs? + ./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/cstring.rs 2> cstring.stderr && exit 1 + sed -e 's,tests/ui,$DIR,' -e '/= help/d' cstring.stderr > normalized.stderr + diff normalized.stderr tests/ui/cstring.stderr + + # TODO: CLIPPY_CONF_DIR / CARGO_MANIFEST_DIR + ) + shell: bash + + - name: Run cargo-cache --autoclean + run: | + cargo install cargo-cache --debug + /usr/bin/find ~/.cargo/bin ! -type d -exec strip {} \; + cargo cache --autoclean + shell: bash From 1717a6f7d5784275337600bc534e35243471c1c5 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 21 Jan 2020 18:44:30 +0100 Subject: [PATCH 044/243] Ignore fmt test in GHA CI This is already checked by clippy_dev.yml GHA --- tests/fmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fmt.rs b/tests/fmt.rs index 2e33c3ed5e5b..e2675fa09683 100644 --- a/tests/fmt.rs +++ b/tests/fmt.rs @@ -3,7 +3,7 @@ use std::process::Command; #[test] fn fmt() { - if option_env!("RUSTC_TEST_SUITE").is_some() { + if option_env!("RUSTC_TEST_SUITE").is_some() || option_env!("GHA_CI").is_some() { return; } From ff8336b0a04237f3c151dd59cd915ad8eedfa093 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 21 Jan 2020 21:40:40 +0100 Subject: [PATCH 045/243] Check if changelog exists --- .github/workflows/clippy_bors.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 6a6d58410f95..2267b46f9fc1 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -16,7 +16,30 @@ env: GHA_CI: 1 jobs: + changelog: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2.0.0 + with: + ref: ${{ github.ref }} + - name: Check Changelog + run: | + MESSAGE=$(git log --format=%B -n 1) + PR=$(echo "$MESSAGE" | grep -o "#[0-9]*" | head -1 | sed -e 's/^#//') + output=$(curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -s "https://api.github.com/repos/rust-lang/rust-clippy/pulls/$PR" | \ + python -c "import sys, json; print(json.load(sys.stdin)['body'])" | \ + grep "^changelog: " | \ + sed "s/changelog: //g") + if [[ -z "$output" ]]; then + echo "ERROR: PR body must contain 'changelog: ...'" + exit 1 + elif [[ "$output" = "none" ]]; then + echo "WARNING: changelog is 'none'" + fi base: + needs: changelog strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] From f5db351a1d502cb65f8807ec2c84f44756099ef3 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 22 Jan 2020 14:56:08 +0100 Subject: [PATCH 046/243] Get {RUSTUP,MULTIRUST}_{HOME,TOOLCHAIN} from runtime environment Keep the fallback to compile-time environment --- src/driver.rs | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index 087c8c67b4a0..097b796e785b 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -281,6 +281,17 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { } } +fn toolchain_path(home: Option, toolchain: Option) -> Option { + home.and_then(|home| { + toolchain.map(|toolchain| { + let mut path = PathBuf::from(home); + path.push("toolchains"); + path.push(toolchain); + path + }) + }) +} + pub fn main() { rustc_driver::init_rustc_env_logger(); lazy_static::initialize(&ICE_HOOK); @@ -301,22 +312,21 @@ pub fn main() { // - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN // - sysroot from rustc in the path // - compile-time environment + // - SYSROOT + // - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN let sys_root_arg = arg_value(&orig_args, "--sysroot", |_| true); let have_sys_root_arg = sys_root_arg.is_some(); let sys_root = sys_root_arg .map(PathBuf::from) .or_else(|| std::env::var("SYSROOT").ok().map(PathBuf::from)) .or_else(|| { - let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); - let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); - home.and_then(|home| { - toolchain.map(|toolchain| { - let mut path = PathBuf::from(home); - path.push("toolchains"); - path.push(toolchain); - path - }) - }) + let home = std::env::var("RUSTUP_HOME") + .or_else(|_| std::env::var("MULTIRUST_HOME")) + .ok(); + let toolchain = std::env::var("RUSTUP_TOOLCHAIN") + .or_else(|_| std::env::var("MULTIRUST_TOOLCHAIN")) + .ok(); + toolchain_path(home, toolchain) }) .or_else(|| { Command::new("rustc") @@ -328,6 +338,15 @@ pub fn main() { .map(|s| PathBuf::from(s.trim())) }) .or_else(|| option_env!("SYSROOT").map(PathBuf::from)) + .or_else(|| { + let home = option_env!("RUSTUP_HOME") + .or(option_env!("MULTIRUST_HOME")) + .map(ToString::to_string); + let toolchain = option_env!("RUSTUP_TOOLCHAIN") + .or(option_env!("MULTIRUST_TOOLCHAIN")) + .map(ToString::to_string); + toolchain_path(home, toolchain) + }) .map(|pb| pb.to_string_lossy().to_string()) .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); From 66b5e2212ddc33c437c3dc130ffe081c81d5b551 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 22 Jan 2020 17:06:13 +0100 Subject: [PATCH 047/243] Add Clippy Test to GHA --- .github/workflows/clippy.yml | 98 ++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 .github/workflows/clippy.yml diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml new file mode 100644 index 000000000000..ae1148e96cb9 --- /dev/null +++ b/.github/workflows/clippy.yml @@ -0,0 +1,98 @@ +name: Clippy Test + +on: + push: + # Ignore bors branches, since they are covered by `clippy_bors.yml` + branches-ignore: [auto, try] + # Don't run Clippy tests, when only textfiles were modified + paths-ignore: + - 'COPYRIGHT' + - 'LICENSE-*' + - '**.md' + - '**.txt' + pull_request: + # Don't run Clippy tests, when only textfiles were modified + paths-ignore: + - 'COPYRIGHT' + - 'LICENSE-*' + - '**.md' + - '**.txt' + +env: + RUST_BACKTRACE: 1 + CARGO_TARGET_DIR: '${{ github.workspace }}/target' + GHA_CI: 1 + +jobs: + base: + runs-on: ubuntu-latest + + steps: + - name: rust-toolchain + uses: actions-rs/toolchain@v1.0.3 + with: + toolchain: nightly + target: x86_64-unknown-linux-gnu + profile: minimal + - name: Cache cargo dir + uses: actions/cache@v1 + with: + path: ~/.cargo + key: ${{ runner.os }}-x86_64-unknown-linux-gnu + - name: Checkout + uses: actions/checkout@v2.0.0 + - name: Master Toolchain Setup + run: bash setup-toolchain.sh + + - name: Set LD_LIBRARY_PATH (Linux) + run: | + SYSROOT=$(rustc --print sysroot) + echo "::set-env name=LD_LIBRARY_PATH::${SYSROOT}/lib${LD_LIBRARY_PATH+:${LD_LIBRARY_PATH}}" + - name: Build + run: cargo build --features deny-warnings + - name: Test + run: cargo test --features deny-warnings + - name: Test clippy_lints + run: cargo test --features deny-warnings + working-directory: clippy_lints + - name: Test rustc_tools_util + run: cargo test --features deny-warnings + working-directory: rustc_tools_util + - name: Test clippy_dev + run: cargo test --features deny-warnings + working-directory: clippy_dev + - name: Test cargo-clippy + run: ../target/debug/cargo-clippy + working-directory: clippy_workspace_tests + - name: Test clippy-driver + run: | + ( + set -ex + # Check sysroot handling + sysroot=$(./target/debug/clippy-driver --print sysroot) + test "$sysroot" = "$(rustc --print sysroot)" + + desired_sysroot=/tmp + sysroot=$(./target/debug/clippy-driver --sysroot $desired_sysroot --print sysroot) + test "$sysroot" = $desired_sysroot + + sysroot=$(SYSROOT=$desired_sysroot ./target/debug/clippy-driver --print sysroot) + test "$sysroot" = $desired_sysroot + + # Make sure this isn't set - clippy-driver should cope without it + unset CARGO_MANIFEST_DIR + + # Run a lint and make sure it produces the expected output. It's also expected to exit with code 1 + # FIXME: How to match the clippy invocation in compile-test.rs? + ./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/cstring.rs 2> cstring.stderr && exit 1 + sed -e 's,tests/ui,$DIR,' -e '/= help/d' cstring.stderr > normalized.stderr + diff normalized.stderr tests/ui/cstring.stderr + + # TODO: CLIPPY_CONF_DIR / CARGO_MANIFEST_DIR + ) + + - name: Run cargo-cache --autoclean + run: | + cargo install cargo-cache --debug + find ~/.cargo/bin ! -type d -exec strip {} \; + cargo cache --autoclean From 92811675ce14d717d04d5d9e8dd89172cbcb0b57 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 22 Jan 2020 20:00:41 +0100 Subject: [PATCH 048/243] Move integration tests in clippy_bors.yml Some call it the integration integration --- .github/workflows/clippy_bors.yml | 55 +++++++++++++++++++++++- .github/workflows/integration.yml | 69 ------------------------------- 2 files changed, 54 insertions(+), 70 deletions(-) delete mode 100644 .github/workflows/integration.yml diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 2267b46f9fc1..99e2cdfa8e29 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -3,7 +3,7 @@ name: Clippy Test (bors) on: push: branches: [auto, try] - # Don't run Clippy tests, when only textfiles were modified + # Don't run tests, when only textfiles were modified paths-ignore: - 'COPYRIGHT' - 'LICENSE-*' @@ -167,3 +167,56 @@ jobs: /usr/bin/find ~/.cargo/bin ! -type d -exec strip {} \; cargo cache --autoclean shell: bash + integration: + needs: changelog + strategy: + fail-fast: false + matrix: + integration: + - 'rust-lang/cargo' + - 'rust-lang/rls' + - 'rust-lang/chalk' + - 'rust-lang/rustfmt' + - 'Marwes/combine' + - 'Geal/nom' + - 'rust-lang/stdarch' + - 'serde-rs/serde' + - 'chronotope/chrono' + - 'hyperium/hyper' + - 'rust-random/rand' + - 'rust-lang/futures-rs' + - 'rust-itertools/itertools' + - 'rust-lang-nursery/failure' + - 'rust-lang/log' + + runs-on: ubuntu-latest + + steps: + - name: rust-toolchain + uses: actions-rs/toolchain@v1.0.3 + with: + toolchain: nightly + target: x86_64-unknown-linux-gnu + profile: minimal + - name: Cache cargo dir + uses: actions/cache@v1 + with: + path: ~/.cargo + key: ${{ runner.os }}-x86_64-unknown-linux-gnu + - name: Checkout + uses: actions/checkout@v2.0.0 + - name: Master Toolchain Setup + run: bash setup-toolchain.sh + + - name: Build + run: cargo build --features integration + - name: Test ${{ matrix.integration }} + run: cargo test --test integration --features integration + env: + INTEGRATION: ${{ matrix.integration }} + + - name: Run cargo-cache --autoclean + run: | + cargo install cargo-cache --debug + find ~/.cargo/bin ! -type d -exec strip {} \; + cargo cache --autoclean diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml deleted file mode 100644 index fc05ee9b9210..000000000000 --- a/.github/workflows/integration.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: Integration - -on: - push: - branches: - - auto - - try - # Don't run integration tests, when only textfiles were modified - paths-ignore: - - 'COPYRIGHT' - - 'LICENSE-*' - - '**.md' - - '**.txt' - -env: - RUST_BACKTRACE: 1 - -jobs: - integration: - strategy: - fail-fast: false - matrix: - integration: - - 'rust-lang/rls' - - 'rust-lang/cargo' - - 'rust-lang/chalk' - - 'Geal/nom' - - 'rust-lang/rustfmt' - - 'hyperium/hyper' - - 'rust-itertools/itertools' - - 'serde-rs/serde' - - 'rust-lang/stdarch' - - 'rust-random/rand' - - 'rust-lang/futures-rs' - - 'Marwes/combine' - - 'rust-lang-nursery/failure' - - 'rust-lang/log' - - 'chronotope/chrono' - runs-on: ubuntu-latest - - steps: - - name: rust-toolchain - uses: actions-rs/toolchain@v1.0.3 - with: - toolchain: nightly - target: x86_64-unknown-linux-gnu - profile: minimal - - name: Cache cargo dir - uses: actions/cache@v1 - with: - path: ~/.cargo - key: ${{ runner.os }}-x86_64-unknown-linux-gnu - - name: Checkout - uses: actions/checkout@v2.0.0 - - name: Master Toolchain Setup - run: bash setup-toolchain.sh - - - name: Build - run: cargo build --features integration - - name: Test ${{ matrix.integration }} - run: cargo test --test integration --features integration - env: - INTEGRATION: ${{ matrix.integration }} - - - name: Run cargo-cache --autoclean - run: | - cargo install cargo-cache --debug - find ~/.cargo/bin ! -type d -exec strip {} \; - cargo cache --autoclean From 893e261a99f74b3b925ab66ccfef45acb8b2d82b Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 22 Jan 2020 21:00:31 +0100 Subject: [PATCH 049/243] Add deployment to GHA --- .github/workflows/deploy.yml | 72 ++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 000000000000..100adbadd5ab --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,72 @@ +name: Deploy + +on: + push: + branches: master + release: + types: [created] + +env: + TARGET_BRANCH: 'gh-pages' + SHA: '${{ github.sha }}' + SSH_REPO: 'git@github.com:${{ github.repository }}.git' + TAG_NAME: '${{ github.event.release.GITHUB_REF }}' + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2.0.0 + - name: Checkout + uses: actions/checkout@v2.0.0 + with: + ref: ${{ env.TARGET_BRANCH }} + path: 'out' + - name: Deploy + run: | + set -ex + + echo "Removing the current docs for master" + rm -rf out/master/ || exit 0 + + echo "Making the docs for master" + mkdir out/master/ + cp util/gh-pages/index.html out/master + python ./util/export.py out/master/lints.json + + if [[ -n $TAG_NAME ]]; then + echo "Save the doc for the current tag ($TAG_NAME) and point current/ to it" + cp -r out/master "out/$TAG_NAME" + rm -f out/current + ln -s "$TAG_NAME" out/current + fi + + # Generate version index that is shown as root index page + cp util/gh-pages/versions.html out/index.html + + cd out + cat <<-EOF | python - > versions.json + import os, json + print json.dumps([ + dir for dir in os.listdir(".") if not dir.startswith(".") and os.path.isdir(dir) + ]) + EOF + + # Now let's go have some fun with the cloned repo + git config user.name "GHA CI" + git config user.email "gha@ci.invalid" + + if git diff --exit-code --quiet; then + echo "No changes to the output on this push; exiting." + exit 0 + fi + + git add . + git commit -m "Automatic deploy to GitHub Pages: ${SHA}" + + eval "$(ssh-agent -s)" + ssh-add - <<< "${{ secrets.DEPLOY_KEY }}" + + git push "$SSH_REPO" "$TARGET_BRANCH" From 8f45387490eecf46a8f7934bd48116b6be727261 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 23 Jan 2020 10:36:51 +0100 Subject: [PATCH 050/243] Small change to comment in .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f1f4fa4e242a..adf5e8feddf4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -# Used by Travis to be able to push: +# Used by CI to be able to push: /.github/deploy_key out From d7620a3e62a0097c990a4abda917c8e2a5115765 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 23 Jan 2020 10:22:02 +0100 Subject: [PATCH 051/243] Add GHA badge to README.md Add a FIXME to Cargo.toml --- Cargo.toml | 1 + README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 84b96a329140..aefbcec15f51 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ publish = false [badges] travis-ci = { repository = "rust-lang/rust-clippy" } appveyor = { repository = "rust-lang/rust-clippy" } +# FIXME(flip1995): Add GHA badge once rust-lang/crates.io#1838 is merged [[bin]] name = "cargo-clippy" diff --git a/README.md b/README.md index af2331fa5331..fe62dadfcbf0 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![Build Status](https://travis-ci.com/rust-lang/rust-clippy.svg?branch=master)](https://travis-ci.com/rust-lang/rust-clippy) [![Windows Build status](https://ci.appveyor.com/api/projects/status/id677xpw1dguo7iw?svg=true)](https://ci.appveyor.com/project/rust-lang-libs/rust-clippy) +[![Clippy Test](https://github.com/rust-lang/rust-clippy/workflows/Clippy%20Test/badge.svg?branch=master&event=push)](https://github.com/rust-lang/rust-clippy/actions?query=workflow%3A%22Clippy+Test%22+event%3Apush+branch%3Amaster) [![License: MIT OR Apache-2.0](https://img.shields.io/crates/l/clippy.svg)](#license) A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. From b9580fcef7a564fedf93e8f2237a089cd9b36fee Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 23 Jan 2020 14:40:37 +0100 Subject: [PATCH 052/243] Cancle builds on new commits --- .github/workflows/clippy.yml | 3 +++ .github/workflows/clippy_bors.yml | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index ae1148e96cb9..7997344aabd0 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -28,6 +28,9 @@ jobs: runs-on: ubuntu-latest steps: + - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master + with: + github_token: "${{ secrets.github_token }}" - name: rust-toolchain uses: actions-rs/toolchain@v1.0.3 with: diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 99e2cdfa8e29..85cd7cbecb9e 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -20,6 +20,9 @@ jobs: runs-on: ubuntu-latest steps: + - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master + with: + github_token: "${{ secrets.github_token }}" - name: Checkout uses: actions/checkout@v2.0.0 with: @@ -65,6 +68,9 @@ jobs: runs-on: ${{ matrix.os }} steps: + - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master + with: + github_token: "${{ secrets.github_token }}" - name: Install dependencies (Linux-i686) run: | sudo dpkg --add-architecture i386 @@ -192,6 +198,9 @@ jobs: runs-on: ubuntu-latest steps: + - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master + with: + github_token: "${{ secrets.github_token }}" - name: rust-toolchain uses: actions-rs/toolchain@v1.0.3 with: From e59361f723ac048a8328f4974ed61e963825413a Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 23 Jan 2020 15:47:11 +0100 Subject: [PATCH 053/243] Limit parallel jobs on try/r+ runs Rate limit of 60 applies org wide, let's not spam. Thanks pietroalbini for the hint --- .github/workflows/clippy_bors.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 85cd7cbecb9e..cb2041e49905 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -177,6 +177,7 @@ jobs: needs: changelog strategy: fail-fast: false + max-parallel: 6 matrix: integration: - 'rust-lang/cargo' From 935b94d80b4456c0c9e50526af2c9f441b846949 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 24 Jan 2020 14:34:25 +0100 Subject: [PATCH 054/243] Sort output of export.py script --- util/export.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/util/export.py b/util/export.py index e8fc4d84ea4f..5d1bd60acf3d 100755 --- a/util/export.py +++ b/util/export.py @@ -71,7 +71,9 @@ def main(): outfile = sys.argv[1] if len(sys.argv) > 1 else "util/gh-pages/lints.json" with open(outfile, "w") as fp: - json.dump(list(lints.values()), fp, indent=2) + lints = list(lints.values()) + lints.sort(key=lambda x: x['id']) + json.dump(lints, fp, indent=2) log.info("wrote JSON for great justice") From ea780a69f3d1d47eaacd2811ab7d742c1627b3d5 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sun, 26 Jan 2020 15:13:14 +0100 Subject: [PATCH 055/243] Extract driver test --- .github/driver.sh | 29 ++++++++++++++++++++++++++++ .github/workflows/clippy.yml | 28 +++------------------------ .github/workflows/clippy_bors.yml | 32 +++---------------------------- 3 files changed, 35 insertions(+), 54 deletions(-) create mode 100644 .github/driver.sh diff --git a/.github/driver.sh b/.github/driver.sh new file mode 100644 index 000000000000..eb81e45a64ea --- /dev/null +++ b/.github/driver.sh @@ -0,0 +1,29 @@ +#! /bin/bash + +set -ex + +# Check sysroot handling +sysroot=$(./target/debug/clippy-driver --print sysroot) +test "$sysroot" = "$(rustc --print sysroot)" + +if [[ ${OS} == "Windows" ]]; then + desired_sysroot=C:/tmp +else + desired_sysroot=/tmp +fi +sysroot=$(./target/debug/clippy-driver --sysroot $desired_sysroot --print sysroot) +test "$sysroot" = $desired_sysroot + +sysroot=$(SYSROOT=$desired_sysroot ./target/debug/clippy-driver --print sysroot) +test "$sysroot" = $desired_sysroot + +# Make sure this isn't set - clippy-driver should cope without it +unset CARGO_MANIFEST_DIR + +# Run a lint and make sure it produces the expected output. It's also expected to exit with code 1 +# FIXME: How to match the clippy invocation in compile-test.rs? +./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/cstring.rs 2> cstring.stderr && exit 1 +sed -e "s,tests/ui,\$DIR," -e "/= help/d" cstring.stderr > normalized.stderr +diff normalized.stderr tests/ui/cstring.stderr + +# TODO: CLIPPY_CONF_DIR / CARGO_MANIFEST_DIR diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 7997344aabd0..9661f826abd3 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -68,31 +68,9 @@ jobs: run: ../target/debug/cargo-clippy working-directory: clippy_workspace_tests - name: Test clippy-driver - run: | - ( - set -ex - # Check sysroot handling - sysroot=$(./target/debug/clippy-driver --print sysroot) - test "$sysroot" = "$(rustc --print sysroot)" - - desired_sysroot=/tmp - sysroot=$(./target/debug/clippy-driver --sysroot $desired_sysroot --print sysroot) - test "$sysroot" = $desired_sysroot - - sysroot=$(SYSROOT=$desired_sysroot ./target/debug/clippy-driver --print sysroot) - test "$sysroot" = $desired_sysroot - - # Make sure this isn't set - clippy-driver should cope without it - unset CARGO_MANIFEST_DIR - - # Run a lint and make sure it produces the expected output. It's also expected to exit with code 1 - # FIXME: How to match the clippy invocation in compile-test.rs? - ./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/cstring.rs 2> cstring.stderr && exit 1 - sed -e 's,tests/ui,$DIR,' -e '/= help/d' cstring.stderr > normalized.stderr - diff normalized.stderr tests/ui/cstring.stderr - - # TODO: CLIPPY_CONF_DIR / CARGO_MANIFEST_DIR - ) + run: bash .github/driver.sh + env: + OS: ${{ runner.os }} - name: Run cargo-cache --autoclean run: | diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index cb2041e49905..49e4251f9dae 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -136,36 +136,10 @@ jobs: shell: bash working-directory: clippy_workspace_tests - name: Test clippy-driver - run: | - ( - set -ex - # Check sysroot handling - sysroot=$(./target/debug/clippy-driver --print sysroot) - test "$sysroot" = "$(rustc --print sysroot)" - - if [[ ${{ runner.os }} == "Windows" ]]; then - desired_sysroot=C:/tmp - else - desired_sysroot=/tmp - fi - sysroot=$(./target/debug/clippy-driver --sysroot $desired_sysroot --print sysroot) - test "$sysroot" = $desired_sysroot - - sysroot=$(SYSROOT=$desired_sysroot ./target/debug/clippy-driver --print sysroot) - test "$sysroot" = $desired_sysroot - - # Make sure this isn't set - clippy-driver should cope without it - unset CARGO_MANIFEST_DIR - - # Run a lint and make sure it produces the expected output. It's also expected to exit with code 1 - # FIXME: How to match the clippy invocation in compile-test.rs? - ./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/cstring.rs 2> cstring.stderr && exit 1 - sed -e 's,tests/ui,$DIR,' -e '/= help/d' cstring.stderr > normalized.stderr - diff normalized.stderr tests/ui/cstring.stderr - - # TODO: CLIPPY_CONF_DIR / CARGO_MANIFEST_DIR - ) + run: bash .github/driver.sh shell: bash + env: + OS: ${{ runner.os }} - name: Run cargo-cache --autoclean run: | From dfdea56e99e864d43206643b85190cb15127cfb9 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sun, 26 Jan 2020 15:40:53 +0100 Subject: [PATCH 056/243] Extract deployment --- .github/deploy.sh | 60 +++++++----------------------------- .github/workflows/deploy.yml | 43 +------------------------- 2 files changed, 12 insertions(+), 91 deletions(-) mode change 100755 => 100644 .github/deploy.sh diff --git a/.github/deploy.sh b/.github/deploy.sh old mode 100755 new mode 100644 index 19dc4017166c..d96c69392a1e --- a/.github/deploy.sh +++ b/.github/deploy.sh @@ -1,20 +1,7 @@ -#!/bin/bash - -# Automatically deploy on gh-pages +#! /bin/bash set -ex -SOURCE_BRANCH="master" -TARGET_BRANCH="gh-pages" - -# Save some useful information -REPO=$(git config remote.origin.url) -SSH_REPO=${REPO/https:\/\/github.com\//git@github.com:} -SHA=$(git rev-parse --verify HEAD) - -# Clone the existing gh-pages for this repo into out/ -git clone --quiet --single-branch --branch "$TARGET_BRANCH" "$REPO" out - echo "Removing the current docs for master" rm -rf out/master/ || exit 0 @@ -23,59 +10,34 @@ mkdir out/master/ cp util/gh-pages/index.html out/master python ./util/export.py out/master/lints.json -if [[ -n "$TRAVIS_TAG" ]]; then - echo "Save the doc for the current tag ($TRAVIS_TAG) and point current/ to it" - cp -r out/master "out/$TRAVIS_TAG" - rm -f out/current - ln -s "$TRAVIS_TAG" out/current +if [[ -n $TAG_NAME ]]; then + echo "Save the doc for the current tag ($TAG_NAME) and point current/ to it" + cp -r out/master "out/$TAG_NAME" + rm -f out/current + ln -s "$TAG_NAME" out/current fi # Generate version index that is shown as root index page cp util/gh-pages/versions.html out/index.html -pushd out +cd out cat <<-EOF | python - > versions.json import os, json print json.dumps([ dir for dir in os.listdir(".") if not dir.startswith(".") and os.path.isdir(dir) ]) EOF -popd - -# Pull requests and commits to other branches shouldn't try to deploy, just build to verify -if [[ "$TRAVIS_PULL_REQUEST" != "false" ]] || [[ "$TRAVIS_BRANCH" != "$SOURCE_BRANCH" ]]; then - # Tags should deploy - if [[ -z "$TRAVIS_TAG" ]]; then - echo "Generated, won't push" - exit 0 - fi -fi # Now let's go have some fun with the cloned repo -cd out -git config user.name "Travis CI" -git config user.email "travis@ci.invalid" +git config user.name "GHA CI" +git config user.email "gha@ci.invalid" if git diff --exit-code --quiet; then - echo "No changes to the output on this push; exiting." - exit 0 + echo "No changes to the output on this push; exiting." + exit 0 fi -cd - -# Get the deploy key by using Travis's stored variables to decrypt deploy_key.enc -ENCRYPTION_LABEL=e3a2d77100be -ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key" -ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv" -ENCRYPTED_KEY=${!ENCRYPTED_KEY_VAR} -ENCRYPTED_IV=${!ENCRYPTED_IV_VAR} -openssl aes-256-cbc -K "$ENCRYPTED_KEY" -iv "$ENCRYPTED_IV" -in .github/deploy_key.enc -out .github/deploy_key -d -chmod 600 .github/deploy_key -eval "$(ssh-agent -s)" -ssh-add .github/deploy_key - -cd out git add . git commit -m "Automatic deploy to GitHub Pages: ${SHA}" -# Now that we're all set up, we can push. git push "$SSH_REPO" "$TARGET_BRANCH" diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 100adbadd5ab..a3c9b1784a18 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -26,47 +26,6 @@ jobs: path: 'out' - name: Deploy run: | - set -ex - - echo "Removing the current docs for master" - rm -rf out/master/ || exit 0 - - echo "Making the docs for master" - mkdir out/master/ - cp util/gh-pages/index.html out/master - python ./util/export.py out/master/lints.json - - if [[ -n $TAG_NAME ]]; then - echo "Save the doc for the current tag ($TAG_NAME) and point current/ to it" - cp -r out/master "out/$TAG_NAME" - rm -f out/current - ln -s "$TAG_NAME" out/current - fi - - # Generate version index that is shown as root index page - cp util/gh-pages/versions.html out/index.html - - cd out - cat <<-EOF | python - > versions.json - import os, json - print json.dumps([ - dir for dir in os.listdir(".") if not dir.startswith(".") and os.path.isdir(dir) - ]) - EOF - - # Now let's go have some fun with the cloned repo - git config user.name "GHA CI" - git config user.email "gha@ci.invalid" - - if git diff --exit-code --quiet; then - echo "No changes to the output on this push; exiting." - exit 0 - fi - - git add . - git commit -m "Automatic deploy to GitHub Pages: ${SHA}" - eval "$(ssh-agent -s)" ssh-add - <<< "${{ secrets.DEPLOY_KEY }}" - - git push "$SSH_REPO" "$TARGET_BRANCH" + bash .github/deploy.sh From ab43951d418301cf20f6ff97b8023b80730730c7 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 30 Jan 2020 17:03:45 +0100 Subject: [PATCH 057/243] Allow non-ascii characters in changelog check --- .github/workflows/clippy_bors.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 49e4251f9dae..15ef44aa1f26 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -41,6 +41,8 @@ jobs: elif [[ "$output" = "none" ]]; then echo "WARNING: changelog is 'none'" fi + env: + PYTHONIOENCODING: 'utf-8' base: needs: changelog strategy: From 1ceeb13e0ad12d044d7bcc0c4ca03c8414dd5ee9 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 31 Jan 2020 14:42:44 +0100 Subject: [PATCH 058/243] Build Clippy before running integration tests --- .github/workflows/clippy_bors.yml | 56 ++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 15ef44aa1f26..e84e3baec625 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -149,8 +149,50 @@ jobs: /usr/bin/find ~/.cargo/bin ! -type d -exec strip {} \; cargo cache --autoclean shell: bash - integration: + integration_build: needs: changelog + runs-on: ubuntu-latest + + steps: + - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master + with: + github_token: "${{ secrets.github_token }}" + - name: rust-toolchain + uses: actions-rs/toolchain@v1.0.3 + with: + toolchain: nightly + target: x86_64-unknown-linux-gnu + profile: minimal + - name: Cache cargo dir + uses: actions/cache@v1 + with: + path: ~/.cargo + key: ${{ runner.os }}-x86_64-unknown-linux-gnu + - name: Checkout + uses: actions/checkout@v2.0.0 + - name: Master Toolchain Setup + run: bash setup-toolchain.sh + + - name: Build Integration Test + run: cargo test --test integration --features integration --no-run + - name: Extract Binaries + run: | + DIR=$CARGO_TARGET_DIR/debug + find $DIR ! -executable -o -type d ! -path $DIR | xargs rm -rf + mv $DIR/integration-* $DIR/integration + - name: Upload Binaries + uses: actions/upload-artifact@v1 + with: + name: target + path: target + + - name: Run cargo-cache --autoclean + run: | + cargo install cargo-cache --debug + find ~/.cargo/bin ! -type d -exec strip {} \; + cargo cache --autoclean + integration: + needs: integration_build strategy: fail-fast: false max-parallel: 6 @@ -194,12 +236,18 @@ jobs: - name: Master Toolchain Setup run: bash setup-toolchain.sh - - name: Build - run: cargo build --features integration + - name: Download target dir + uses: actions/download-artifact@v1 + with: + name: target + path: target + - name: Make Binaries Executable + run: chmod +x $CARGO_TARGET_DIR/debug/* - name: Test ${{ matrix.integration }} - run: cargo test --test integration --features integration + run: $CARGO_TARGET_DIR/debug/integration env: INTEGRATION: ${{ matrix.integration }} + RUSTUP_TOOLCHAIN: master - name: Run cargo-cache --autoclean run: | From 095287dbc86c7264d221aafc08ac1961140b0db4 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 31 Jan 2020 14:43:02 +0100 Subject: [PATCH 059/243] Add two more error causes to integration test --- tests/integration.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/integration.rs b/tests/integration.rs index d14ced8ad4e7..74f9a854dc1f 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -59,6 +59,10 @@ fn integration_test() { panic!("query stack during panic in the output"); } else if stderr.contains("E0463") { panic!("error: E0463"); + } else if stderr.contains("E0514") { + panic!("incompatible crate versions"); + } else if stderr.contains("failed to run `rustc` to learn about target-specific information") { + panic!("couldn't find librustc_driver, consider setting `LD_LIBRARY_PATH`"); } match output.status.code() { From 813d3192bb0267ba2971ab85c115d52119848ff5 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 31 Jan 2020 14:44:55 +0100 Subject: [PATCH 060/243] Use hash of Cargo.lock file in cache name --- .github/workflows/clippy.yml | 10 +++++++--- .github/workflows/clippy_bors.yml | 30 +++++++++++++++++++++--------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 9661f826abd3..b4bd9f540bd1 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -37,13 +37,17 @@ jobs: toolchain: nightly target: x86_64-unknown-linux-gnu profile: minimal + - name: Checkout + uses: actions/checkout@v2.0.0 + - name: Run cargo update + run: cargo update - name: Cache cargo dir uses: actions/cache@v1 with: path: ~/.cargo - key: ${{ runner.os }}-x86_64-unknown-linux-gnu - - name: Checkout - uses: actions/checkout@v2.0.0 + key: ${{ runner.os }}-x86_64-unknown-linux-gnu-${{ hashFiles('Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-x86_64-unknown-linux-gnu - name: Master Toolchain Setup run: bash setup-toolchain.sh diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index e84e3baec625..498b109f7803 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -85,13 +85,17 @@ jobs: toolchain: nightly target: ${{ matrix.host }} profile: minimal + - name: Checkout + uses: actions/checkout@v2.0.0 + - name: Run cargo update + run: cargo update - name: Cache cargo dir uses: actions/cache@v1 with: path: ~/.cargo - key: ${{ runner.os }}-${{ matrix.host }} - - name: Checkout - uses: actions/checkout@v2.0.0 + key: ${{ runner.os }}-${{ matrix.host }}-${{ hashFiles('Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-${{ matrix.host }} - name: Master Toolchain Setup run: bash setup-toolchain.sh env: @@ -163,13 +167,17 @@ jobs: toolchain: nightly target: x86_64-unknown-linux-gnu profile: minimal + - name: Checkout + uses: actions/checkout@v2.0.0 + - name: Run cargo update + run: cargo update - name: Cache cargo dir uses: actions/cache@v1 with: path: ~/.cargo - key: ${{ runner.os }}-x86_64-unknown-linux-gnu - - name: Checkout - uses: actions/checkout@v2.0.0 + key: ${{ runner.os }}-x86_64-unknown-linux-gnu-${{ hashFiles('Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-x86_64-unknown-linux-gnu - name: Master Toolchain Setup run: bash setup-toolchain.sh @@ -226,13 +234,17 @@ jobs: toolchain: nightly target: x86_64-unknown-linux-gnu profile: minimal + - name: Checkout + uses: actions/checkout@v2.0.0 + - name: Run cargo update + run: cargo update - name: Cache cargo dir uses: actions/cache@v1 with: path: ~/.cargo - key: ${{ runner.os }}-x86_64-unknown-linux-gnu - - name: Checkout - uses: actions/checkout@v2.0.0 + key: ${{ runner.os }}-x86_64-unknown-linux-gnu-${{ hashFiles('Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-x86_64-unknown-linux-gnu - name: Master Toolchain Setup run: bash setup-toolchain.sh From b8b47ab6fe4e1c18db2685c406a508fe145c7de9 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 4 Feb 2020 17:33:50 +0100 Subject: [PATCH 061/243] Add bors dummy jobs --- .github/workflows/clippy_bors.yml | 26 ++++++++++++++++++++++++++ .github/workflows/clippy_dev.yml | 26 ++++++++++++++++++++++++++ .github/workflows/remark.yml | 26 ++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 498b109f7803..c06d44185e49 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -266,3 +266,29 @@ jobs: cargo install cargo-cache --debug find ~/.cargo/bin ! -type d -exec strip {} \; cargo cache --autoclean + + # These jobs doesn't actually test anything, but they're only used to tell + # bors the build completed, as there is no practical way to detect when a + # workflow is successful listening to webhooks only. + # + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + + end-success: + name: bors test finished + if: github.event.pusher.name == 'bors' && success() + runs-on: ubuntu-latest + needs: [base, integration] + + steps: + - name: Mark the job as successful + run: exit 0 + + end-failure: + name: bors test finished + if: github.event.pusher.name == 'bors' && (failure() || cancelled()) + runs-on: ubuntu-latest + needs: [base, integration] + + steps: + - name: Mark the job as a failure + run: exit 1 diff --git a/.github/workflows/clippy_dev.yml b/.github/workflows/clippy_dev.yml index d054b6ba750c..e4409ee80a5b 100644 --- a/.github/workflows/clippy_dev.yml +++ b/.github/workflows/clippy_dev.yml @@ -42,3 +42,29 @@ jobs: run: cargo dev update_lints --check - name: Test fmt run: cargo dev fmt --check + + # These jobs doesn't actually test anything, but they're only used to tell + # bors the build completed, as there is no practical way to detect when a + # workflow is successful listening to webhooks only. + # + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + + end-success: + name: bors dev test finished + if: github.event.pusher.name == 'bors' && success() + runs-on: ubuntu-latest + needs: [clippy_dev] + + steps: + - name: Mark the job as successful + run: exit 0 + + end-failure: + name: bors dev test finished + if: github.event.pusher.name == 'bors' && (failure() || cancelled()) + runs-on: ubuntu-latest + needs: [clippy_dev] + + steps: + - name: Mark the job as a failure + run: exit 1 diff --git a/.github/workflows/remark.yml b/.github/workflows/remark.yml index 8e311c75df08..5256c538e371 100644 --- a/.github/workflows/remark.yml +++ b/.github/workflows/remark.yml @@ -22,3 +22,29 @@ jobs: - name: Check *.md files run: git ls-files -z '*.md' | xargs -0 -n 1 -I {} ./node_modules/.bin/remark {} -u lint -f > /dev/null + + # These jobs doesn't actually test anything, but they're only used to tell + # bors the build completed, as there is no practical way to detect when a + # workflow is successful listening to webhooks only. + # + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + + end-success: + name: bors remark test finished + if: github.event.pusher.name == 'bors' && success() + runs-on: ubuntu-latest + needs: [remark] + + steps: + - name: Mark the job as successful + run: exit 0 + + end-failure: + name: bors remark test finished + if: github.event.pusher.name == 'bors' && (failure() || cancelled()) + runs-on: ubuntu-latest + needs: [remark] + + steps: + - name: Mark the job as a failure + run: exit 1 From abb095ddedd3c918d7c55d028d7f134bf4a507d3 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 4 Feb 2020 18:42:45 +0100 Subject: [PATCH 062/243] Run bors checks unconditionally This is important, since bors doesn't know optional jobs. Otherwise bors would time out, when a check doesn't get run. --- .github/workflows/clippy_bors.yml | 6 ------ .github/workflows/clippy_dev.yml | 8 ++------ .github/workflows/remark.yml | 3 +-- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index c06d44185e49..b1b207416a1e 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -3,12 +3,6 @@ name: Clippy Test (bors) on: push: branches: [auto, try] - # Don't run tests, when only textfiles were modified - paths-ignore: - - 'COPYRIGHT' - - 'LICENSE-*' - - '**.md' - - '**.txt' env: RUST_BACKTRACE: 1 diff --git a/.github/workflows/clippy_dev.yml b/.github/workflows/clippy_dev.yml index e4409ee80a5b..f9e5d73a3458 100644 --- a/.github/workflows/clippy_dev.yml +++ b/.github/workflows/clippy_dev.yml @@ -1,14 +1,10 @@ name: Clippy Dev Test on: - # Only run on paths, that get checked by the clippy_dev tool push: - paths: - - 'CAHNGELOG.md' - - 'README.md' - - '**.stderr' - - '**.rs' + branches: [auto, try] pull_request: + # Only run on paths, that get checked by the clippy_dev tool paths: - 'CAHNGELOG.md' - 'README.md' diff --git a/.github/workflows/remark.yml b/.github/workflows/remark.yml index 5256c538e371..8059dbf433bc 100644 --- a/.github/workflows/remark.yml +++ b/.github/workflows/remark.yml @@ -2,8 +2,7 @@ name: Remark on: push: - paths: - - '**.md' + branches: [auto, try] pull_request: paths: - '**.md' From b47dada167dea3d889abd77b7ff584afdaaf0a86 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 7 Feb 2020 22:24:41 +0100 Subject: [PATCH 063/243] Apply review comments --- .github/deploy.sh | 2 +- .github/driver.sh | 2 +- .github/workflows/clippy.yml | 17 ++++++++++++- .github/workflows/clippy_bors.yml | 42 ++++++++++++++++++++++++++++++- .github/workflows/clippy_dev.yml | 6 +++++ .github/workflows/deploy.yml | 4 +++ .github/workflows/remark.yml | 4 +++ tests/fmt.rs | 2 +- 8 files changed, 74 insertions(+), 5 deletions(-) diff --git a/.github/deploy.sh b/.github/deploy.sh index d96c69392a1e..4fcff830aa6f 100644 --- a/.github/deploy.sh +++ b/.github/deploy.sh @@ -1,4 +1,4 @@ -#! /bin/bash +#!/bin/bash set -ex diff --git a/.github/driver.sh b/.github/driver.sh index eb81e45a64ea..a2e87f5eb374 100644 --- a/.github/driver.sh +++ b/.github/driver.sh @@ -1,4 +1,4 @@ -#! /bin/bash +#!/bin/bash set -ex diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index b4bd9f540bd1..fb945060980d 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -21,26 +21,31 @@ on: env: RUST_BACKTRACE: 1 CARGO_TARGET_DIR: '${{ github.workspace }}/target' - GHA_CI: 1 + NO_FMT_TEST: 1 jobs: base: runs-on: ubuntu-latest steps: + # Setup - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master with: github_token: "${{ secrets.github_token }}" + - name: rust-toolchain uses: actions-rs/toolchain@v1.0.3 with: toolchain: nightly target: x86_64-unknown-linux-gnu profile: minimal + - name: Checkout uses: actions/checkout@v2.0.0 + - name: Run cargo update run: cargo update + - name: Cache cargo dir uses: actions/cache@v1 with: @@ -48,34 +53,44 @@ jobs: key: ${{ runner.os }}-x86_64-unknown-linux-gnu-${{ hashFiles('Cargo.lock') }} restore-keys: | ${{ runner.os }}-x86_64-unknown-linux-gnu + - name: Master Toolchain Setup run: bash setup-toolchain.sh + # Run - name: Set LD_LIBRARY_PATH (Linux) run: | SYSROOT=$(rustc --print sysroot) echo "::set-env name=LD_LIBRARY_PATH::${SYSROOT}/lib${LD_LIBRARY_PATH+:${LD_LIBRARY_PATH}}" + - name: Build run: cargo build --features deny-warnings + - name: Test run: cargo test --features deny-warnings + - name: Test clippy_lints run: cargo test --features deny-warnings working-directory: clippy_lints + - name: Test rustc_tools_util run: cargo test --features deny-warnings working-directory: rustc_tools_util + - name: Test clippy_dev run: cargo test --features deny-warnings working-directory: clippy_dev + - name: Test cargo-clippy run: ../target/debug/cargo-clippy working-directory: clippy_workspace_tests + - name: Test clippy-driver run: bash .github/driver.sh env: OS: ${{ runner.os }} + # Cleanup - name: Run cargo-cache --autoclean run: | cargo install cargo-cache --debug diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index b1b207416a1e..a690573180f0 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -7,7 +7,7 @@ on: env: RUST_BACKTRACE: 1 CARGO_TARGET_DIR: '${{ github.workspace }}/target' - GHA_CI: 1 + NO_FMT_TEST: 1 jobs: changelog: @@ -21,6 +21,8 @@ jobs: uses: actions/checkout@v2.0.0 with: ref: ${{ github.ref }} + + # Run - name: Check Changelog run: | MESSAGE=$(git log --format=%B -n 1) @@ -64,25 +66,31 @@ jobs: runs-on: ${{ matrix.os }} steps: + # Setup - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master with: github_token: "${{ secrets.github_token }}" + - name: Install dependencies (Linux-i686) run: | sudo dpkg --add-architecture i386 sudo apt-get update sudo apt-get install gcc-multilib libssl-dev:i386 libgit2-dev:i386 if: matrix.host == 'i686-unknown-linux-gnu' + - name: rust-toolchain uses: actions-rs/toolchain@v1.0.3 with: toolchain: nightly target: ${{ matrix.host }} profile: minimal + - name: Checkout uses: actions/checkout@v2.0.0 + - name: Run cargo update run: cargo update + - name: Cache cargo dir uses: actions/cache@v1 with: @@ -90,12 +98,14 @@ jobs: key: ${{ runner.os }}-${{ matrix.host }}-${{ hashFiles('Cargo.lock') }} restore-keys: | ${{ runner.os }}-${{ matrix.host }} + - name: Master Toolchain Setup run: bash setup-toolchain.sh env: HOST_TOOLCHAIN: ${{ matrix.host }} shell: bash + # Run - name: Set LD_LIBRARY_PATH (Linux) if: runner.os == 'Linux' run: | @@ -113,34 +123,42 @@ jobs: $sysroot = rustc --print sysroot $env:PATH += ';' + $sysroot + '\bin' echo "::set-env name=PATH::$env:PATH" + - name: Build run: cargo build --features deny-warnings shell: bash + - name: Test run: cargo test --features deny-warnings shell: bash + - name: Test clippy_lints run: cargo test --features deny-warnings shell: bash working-directory: clippy_lints + - name: Test rustc_tools_util run: cargo test --features deny-warnings shell: bash working-directory: rustc_tools_util + - name: Test clippy_dev run: cargo test --features deny-warnings shell: bash working-directory: clippy_dev + - name: Test cargo-clippy run: ../target/debug/cargo-clippy shell: bash working-directory: clippy_workspace_tests + - name: Test clippy-driver run: bash .github/driver.sh shell: bash env: OS: ${{ runner.os }} + # Cleanup - name: Run cargo-cache --autoclean run: | cargo install cargo-cache --debug @@ -152,19 +170,24 @@ jobs: runs-on: ubuntu-latest steps: + # Setup - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master with: github_token: "${{ secrets.github_token }}" + - name: rust-toolchain uses: actions-rs/toolchain@v1.0.3 with: toolchain: nightly target: x86_64-unknown-linux-gnu profile: minimal + - name: Checkout uses: actions/checkout@v2.0.0 + - name: Run cargo update run: cargo update + - name: Cache cargo dir uses: actions/cache@v1 with: @@ -172,22 +195,28 @@ jobs: key: ${{ runner.os }}-x86_64-unknown-linux-gnu-${{ hashFiles('Cargo.lock') }} restore-keys: | ${{ runner.os }}-x86_64-unknown-linux-gnu + - name: Master Toolchain Setup run: bash setup-toolchain.sh + # Run - name: Build Integration Test run: cargo test --test integration --features integration --no-run + + # Upload - name: Extract Binaries run: | DIR=$CARGO_TARGET_DIR/debug find $DIR ! -executable -o -type d ! -path $DIR | xargs rm -rf mv $DIR/integration-* $DIR/integration + - name: Upload Binaries uses: actions/upload-artifact@v1 with: name: target path: target + # Cleanup - name: Run cargo-cache --autoclean run: | cargo install cargo-cache --debug @@ -219,19 +248,24 @@ jobs: runs-on: ubuntu-latest steps: + # Setup - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master with: github_token: "${{ secrets.github_token }}" + - name: rust-toolchain uses: actions-rs/toolchain@v1.0.3 with: toolchain: nightly target: x86_64-unknown-linux-gnu profile: minimal + - name: Checkout uses: actions/checkout@v2.0.0 + - name: Run cargo update run: cargo update + - name: Cache cargo dir uses: actions/cache@v1 with: @@ -239,22 +273,28 @@ jobs: key: ${{ runner.os }}-x86_64-unknown-linux-gnu-${{ hashFiles('Cargo.lock') }} restore-keys: | ${{ runner.os }}-x86_64-unknown-linux-gnu + - name: Master Toolchain Setup run: bash setup-toolchain.sh + # Download - name: Download target dir uses: actions/download-artifact@v1 with: name: target path: target + - name: Make Binaries Executable run: chmod +x $CARGO_TARGET_DIR/debug/* + + # Run - name: Test ${{ matrix.integration }} run: $CARGO_TARGET_DIR/debug/integration env: INTEGRATION: ${{ matrix.integration }} RUSTUP_TOOLCHAIN: master + # Cleanup - name: Run cargo-cache --autoclean run: | cargo install cargo-cache --debug diff --git a/.github/workflows/clippy_dev.yml b/.github/workflows/clippy_dev.yml index f9e5d73a3458..d6f5db014a43 100644 --- a/.github/workflows/clippy_dev.yml +++ b/.github/workflows/clippy_dev.yml @@ -19,6 +19,7 @@ jobs: runs-on: ubuntu-latest steps: + # Setup - name: rust-toolchain uses: actions-rs/toolchain@v1.0.3 with: @@ -26,16 +27,21 @@ jobs: target: x86_64-unknown-linux-gnu profile: minimal components: rustfmt + - name: Checkout uses: actions/checkout@v2.0.0 + # Run - name: Build run: cargo build --features deny-warnings working-directory: clippy_dev + - name: Test limit-stderr-length run: cargo dev --limit-stderr-length + - name: Test update_lints run: cargo dev update_lints --check + - name: Test fmt run: cargo dev fmt --check diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index a3c9b1784a18..6f79891358eb 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -17,13 +17,17 @@ jobs: runs-on: ubuntu-latest steps: + # Setup - name: Checkout uses: actions/checkout@v2.0.0 + - name: Checkout uses: actions/checkout@v2.0.0 with: ref: ${{ env.TARGET_BRANCH }} path: 'out' + + # Run - name: Deploy run: | eval "$(ssh-agent -s)" diff --git a/.github/workflows/remark.yml b/.github/workflows/remark.yml index 8059dbf433bc..3544053d399a 100644 --- a/.github/workflows/remark.yml +++ b/.github/workflows/remark.yml @@ -12,13 +12,17 @@ jobs: runs-on: ubuntu-latest steps: + # Setup - name: Checkout uses: actions/checkout@v2.0.0 + - name: Setup Node.js uses: actions/setup-node@v1.1.0 + - name: Install remark run: npm install remark-cli remark-lint remark-lint-maximum-line-length remark-preset-lint-recommended + # Run - name: Check *.md files run: git ls-files -z '*.md' | xargs -0 -n 1 -I {} ./node_modules/.bin/remark {} -u lint -f > /dev/null diff --git a/tests/fmt.rs b/tests/fmt.rs index e2675fa09683..3aff8741f605 100644 --- a/tests/fmt.rs +++ b/tests/fmt.rs @@ -3,7 +3,7 @@ use std::process::Command; #[test] fn fmt() { - if option_env!("RUSTC_TEST_SUITE").is_some() || option_env!("GHA_CI").is_some() { + if option_env!("RUSTC_TEST_SUITE").is_some() || option_env!("NO_FMT_TEST").is_some() { return; } From 622ece3153c7e0cf4144ee468d45d1ed4de19bd0 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 7 Feb 2020 22:27:14 +0100 Subject: [PATCH 064/243] Remove deployment from travis --- .travis.yml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index bd3003d45977..653966784ffe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -152,15 +152,3 @@ script: else ./ci/base-tests.sh && sleep 5 fi - -after_success: - - | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then - set -e - if [[ -z ${INTEGRATION} ]]; then - ./.github/deploy.sh - else - echo "Not deploying, because we're in an integration test run" - fi - set +e - fi From 27453463f2615920fa964625f104d6822c105b32 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 7 Feb 2020 22:33:05 +0100 Subject: [PATCH 065/243] Install all required remark packages in travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 653966784ffe..fa02f5334017 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,7 +48,7 @@ install: . $HOME/.nvm/nvm.sh nvm install stable nvm use stable - npm install remark-cli remark-lint + npm install remark-cli remark-lint remark-lint-maximum-line-length remark-preset-lint-recommended elif [[ "$TRAVIS_OS_NAME" == "windows" ]]; then choco install windows-sdk-10.1 fi From a0a21a8752b3e1616d183c9e407e5d78de39bd1e Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sun, 9 Feb 2020 16:29:03 +0100 Subject: [PATCH 066/243] Use nightly cargo to install cargo-cache Stable cargo install still errors when packages exists, instead of updating it --- .github/workflows/clippy.yml | 2 +- .github/workflows/clippy_bors.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index fb945060980d..0d7d2929000b 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -93,6 +93,6 @@ jobs: # Cleanup - name: Run cargo-cache --autoclean run: | - cargo install cargo-cache --debug + cargo +nightly install cargo-cache --debug find ~/.cargo/bin ! -type d -exec strip {} \; cargo cache --autoclean diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index a690573180f0..0f97e5165e6c 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -161,7 +161,7 @@ jobs: # Cleanup - name: Run cargo-cache --autoclean run: | - cargo install cargo-cache --debug + cargo +nightly install cargo-cache --debug /usr/bin/find ~/.cargo/bin ! -type d -exec strip {} \; cargo cache --autoclean shell: bash @@ -219,7 +219,7 @@ jobs: # Cleanup - name: Run cargo-cache --autoclean run: | - cargo install cargo-cache --debug + cargo +nightly install cargo-cache --debug find ~/.cargo/bin ! -type d -exec strip {} \; cargo cache --autoclean integration: @@ -297,7 +297,7 @@ jobs: # Cleanup - name: Run cargo-cache --autoclean run: | - cargo install cargo-cache --debug + cargo +nightly install cargo-cache --debug find ~/.cargo/bin ! -type d -exec strip {} \; cargo cache --autoclean From 3fac289c3d7f9caea256ce6cc65b54e214aa776e Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 12 Feb 2020 10:01:19 +0100 Subject: [PATCH 067/243] Don't upload target/release in integration_build This dir was generated by compiling RTIM, when no cache is available --- .github/workflows/clippy_bors.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 0f97e5165e6c..d147e0790a0a 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -209,6 +209,7 @@ jobs: DIR=$CARGO_TARGET_DIR/debug find $DIR ! -executable -o -type d ! -path $DIR | xargs rm -rf mv $DIR/integration-* $DIR/integration + rm -rf $CARGO_TARGET_DIR/release - name: Upload Binaries uses: actions/upload-artifact@v1 From b0d25de54a62451cb5699080b69219ac12247023 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 12 Feb 2020 11:02:07 +0100 Subject: [PATCH 068/243] Use list instead of array for branch names This is the officially supported method --- .github/workflows/clippy.yml | 4 +++- .github/workflows/clippy_bors.yml | 4 +++- .github/workflows/clippy_dev.yml | 4 +++- .github/workflows/deploy.yml | 6 ++++-- .github/workflows/remark.yml | 4 +++- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 0d7d2929000b..6a9f64e88bdb 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -3,7 +3,9 @@ name: Clippy Test on: push: # Ignore bors branches, since they are covered by `clippy_bors.yml` - branches-ignore: [auto, try] + branches-ignore: + - auto + - try # Don't run Clippy tests, when only textfiles were modified paths-ignore: - 'COPYRIGHT' diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index d147e0790a0a..f77350f09b94 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -2,7 +2,9 @@ name: Clippy Test (bors) on: push: - branches: [auto, try] + branches: + - auto + - try env: RUST_BACKTRACE: 1 diff --git a/.github/workflows/clippy_dev.yml b/.github/workflows/clippy_dev.yml index d6f5db014a43..9ca2e630cbbb 100644 --- a/.github/workflows/clippy_dev.yml +++ b/.github/workflows/clippy_dev.yml @@ -2,7 +2,9 @@ name: Clippy Dev Test on: push: - branches: [auto, try] + branches: + - auto + - try pull_request: # Only run on paths, that get checked by the clippy_dev tool paths: diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 6f79891358eb..93300b6e124f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -2,9 +2,11 @@ name: Deploy on: push: - branches: master + branches: + - master release: - types: [created] + types: + - created env: TARGET_BRANCH: 'gh-pages' diff --git a/.github/workflows/remark.yml b/.github/workflows/remark.yml index 3544053d399a..cc175e8bf247 100644 --- a/.github/workflows/remark.yml +++ b/.github/workflows/remark.yml @@ -2,7 +2,9 @@ name: Remark on: push: - branches: [auto, try] + branches: + - auto + - try pull_request: paths: - '**.md' From fb59043621f9297d641b16d3a7151c69e70f515e Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 12 Feb 2020 12:13:59 +0100 Subject: [PATCH 069/243] Change badge branch master -> auto For some reason GHA classifies the bors merges on the master branch as a push to the auto branch, even though the workflow got triggered by a push to the master branch. I guess this has something to do with the same commit hash on master+auto directly after the merge? --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fe62dadfcbf0..39cc9310f512 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://travis-ci.com/rust-lang/rust-clippy.svg?branch=master)](https://travis-ci.com/rust-lang/rust-clippy) [![Windows Build status](https://ci.appveyor.com/api/projects/status/id677xpw1dguo7iw?svg=true)](https://ci.appveyor.com/project/rust-lang-libs/rust-clippy) -[![Clippy Test](https://github.com/rust-lang/rust-clippy/workflows/Clippy%20Test/badge.svg?branch=master&event=push)](https://github.com/rust-lang/rust-clippy/actions?query=workflow%3A%22Clippy+Test%22+event%3Apush+branch%3Amaster) +[![Clippy Test](https://github.com/rust-lang/rust-clippy/workflows/Clippy%20Test/badge.svg?branch=auto&event=push)](https://github.com/rust-lang/rust-clippy/actions?query=workflow%3A%22Clippy+Test%22+event%3Apush+branch%3Aauto) [![License: MIT OR Apache-2.0](https://img.shields.io/crates/l/clippy.svg)](#license) A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. From 3241e4fed451b12e0fc347b1a2f884c832f2294e Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 12 Feb 2020 14:49:08 +0100 Subject: [PATCH 070/243] Run deploy workflow on tags, instead of releases --- .github/workflows/deploy.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 93300b6e124f..be40b27440d7 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -4,15 +4,13 @@ on: push: branches: - master - release: - types: - - created + tags: + - rust-1.** env: TARGET_BRANCH: 'gh-pages' SHA: '${{ github.sha }}' SSH_REPO: 'git@github.com:${{ github.repository }}.git' - TAG_NAME: '${{ github.event.release.GITHUB_REF }}' jobs: deploy: @@ -30,6 +28,11 @@ jobs: path: 'out' # Run + - name: Set tag name + if: startswith(github.ref, 'refs/tags/') + run: | + TAG=$(basename ${{ github.ref }}) + echo "::set-env name=TAG_NAME::$TAG" - name: Deploy run: | eval "$(ssh-agent -s)" From b755a7d714c40176958bf9a3da7896b50bebef47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 12 Feb 2020 14:02:38 +0100 Subject: [PATCH 071/243] gha: install cargo-cache with ci-autoclean feature which speeds up build time by a large margin. --- .github/workflows/clippy.yml | 5 ++--- .github/workflows/clippy_bors.yml | 15 ++++++--------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 6a9f64e88bdb..8edf0c23860a 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -95,6 +95,5 @@ jobs: # Cleanup - name: Run cargo-cache --autoclean run: | - cargo +nightly install cargo-cache --debug - find ~/.cargo/bin ! -type d -exec strip {} \; - cargo cache --autoclean + cargo +nightly install cargo-cache --no-default-features --features ci-autoclean cargo-cache + cargo cache diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index f77350f09b94..a4f7b64cb6a7 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -163,9 +163,8 @@ jobs: # Cleanup - name: Run cargo-cache --autoclean run: | - cargo +nightly install cargo-cache --debug - /usr/bin/find ~/.cargo/bin ! -type d -exec strip {} \; - cargo cache --autoclean + cargo +nightly install cargo-cache --no-default-features --features ci-autoclean cargo-cache + cargo cache shell: bash integration_build: needs: changelog @@ -222,9 +221,8 @@ jobs: # Cleanup - name: Run cargo-cache --autoclean run: | - cargo +nightly install cargo-cache --debug - find ~/.cargo/bin ! -type d -exec strip {} \; - cargo cache --autoclean + cargo +nightly install cargo-cache --no-default-features --features ci-autoclean cargo-cache + cargo cache integration: needs: integration_build strategy: @@ -300,9 +298,8 @@ jobs: # Cleanup - name: Run cargo-cache --autoclean run: | - cargo +nightly install cargo-cache --debug - find ~/.cargo/bin ! -type d -exec strip {} \; - cargo cache --autoclean + cargo +nightly install cargo-cache --no-default-features --features ci-autoclean cargo-cache + cargo cache # These jobs doesn't actually test anything, but they're only used to tell # bors the build completed, as there is no practical way to detect when a From 7e0af69f1ce02efc69ca67bd3792969a84949411 Mon Sep 17 00:00:00 2001 From: Lily Chung Date: Wed, 12 Feb 2020 16:50:29 -0800 Subject: [PATCH 072/243] Reclassify chars_next_cmp as a style lint. This makes it consistent with chars_last_cmp. --- src/lintlist/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index d4f94a9b60a4..06a1fca4fdd8 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -191,7 +191,7 @@ pub const ALL_LINTS: [Lint; 355] = [ }, Lint { name: "chars_next_cmp", - group: "complexity", + group: "style", desc: "using `.chars().next()` to check if a string starts with a char", deprecation: None, module: "methods", From 385fd7cd0aa4d95a61962c20e62281c728447ea9 Mon Sep 17 00:00:00 2001 From: Lily Chung Date: Wed, 12 Feb 2020 17:03:49 -0800 Subject: [PATCH 073/243] change in the right place, run update_lints --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/methods/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index f900a99f314d..02cf2d06f04d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1412,6 +1412,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&mem_replace::MEM_REPLACE_OPTION_WITH_NONE), LintId::of(&mem_replace::MEM_REPLACE_WITH_DEFAULT), LintId::of(&methods::CHARS_LAST_CMP), + LintId::of(&methods::CHARS_NEXT_CMP), LintId::of(&methods::INTO_ITER_ON_REF), LintId::of(&methods::ITER_CLONED_COLLECT), LintId::of(&methods::ITER_NTH_ZERO), @@ -1494,7 +1495,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&matches::MATCH_AS_REF), LintId::of(&matches::MATCH_SINGLE_BINDING), LintId::of(&matches::WILDCARD_IN_OR_PATTERNS), - LintId::of(&methods::CHARS_NEXT_CMP), LintId::of(&methods::CLONE_ON_COPY), LintId::of(&methods::FILTER_NEXT), LintId::of(&methods::FLAT_MAP_IDENTITY), diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 82bc8740d1af..716cd74ab92f 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -551,7 +551,7 @@ declare_clippy_lint! { /// if name.starts_with('_') {}; /// ``` pub CHARS_NEXT_CMP, - complexity, + style, "using `.chars().next()` to check if a string starts with a char" } From f77158bc14b991941f92225f85b06d44eb69ee34 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 13 Feb 2020 14:39:29 +0900 Subject: [PATCH 074/243] Fix false positive in `zero_prefixed_literal` --- clippy_lints/src/misc_early.rs | 6 +++++- tests/ui/literals.rs | 1 + tests/ui/literals.stderr | 6 +++--- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index e0e2a0caee4e..b28a61eb6219 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -506,7 +506,11 @@ impl MiscEarlyLints { ); } - if lit_snip.starts_with("0x") && maybe_last_sep_idx >= 3 { + if lit_snip.starts_with("0x") { + if maybe_last_sep_idx <= 2 { + // It's meaningless or causes range error. + return; + } let mut seen = (false, false); for ch in lit_snip.as_bytes()[2..=maybe_last_sep_idx].iter() { match ch { diff --git a/tests/ui/literals.rs b/tests/ui/literals.rs index 20bd872c638c..c299b16c8ce8 100644 --- a/tests/ui/literals.rs +++ b/tests/ui/literals.rs @@ -28,6 +28,7 @@ fn main() { let ok15 = 0xab_cabc_abca_bcab_cabc; let ok16 = 0xFE_BAFE_ABAB_ABCD; let ok17 = 0x123_4567_8901_usize; + let ok18 = 0xF; let fail19 = 12_3456_21; let fail22 = 3__4___23; diff --git a/tests/ui/literals.stderr b/tests/ui/literals.stderr index 9a6388394cd0..0b3af2d8bc35 100644 --- a/tests/ui/literals.stderr +++ b/tests/ui/literals.stderr @@ -50,7 +50,7 @@ LL | let fail8 = 0o123; | ^^^^^ error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:32:18 + --> $DIR/literals.rs:33:18 | LL | let fail19 = 12_3456_21; | ^^^^^^^^^^ help: consider: `12_345_621` @@ -58,13 +58,13 @@ LL | let fail19 = 12_3456_21; = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:33:18 + --> $DIR/literals.rs:34:18 | LL | let fail22 = 3__4___23; | ^^^^^^^^^ help: consider: `3_423` error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:34:18 + --> $DIR/literals.rs:35:18 | LL | let fail23 = 3__16___23; | ^^^^^^^^^^ help: consider: `31_623` From 5e03d5bb067db8ea03e0bb75471fe40daf64f55b Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 13 Feb 2020 17:29:40 +0100 Subject: [PATCH 075/243] Sort versions in json output --- .github/deploy.sh | 10 +++------- util/versions.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 7 deletions(-) create mode 100755 util/versions.py diff --git a/.github/deploy.sh b/.github/deploy.sh index 4fcff830aa6f..59a7cdae866e 100644 --- a/.github/deploy.sh +++ b/.github/deploy.sh @@ -20,14 +20,10 @@ fi # Generate version index that is shown as root index page cp util/gh-pages/versions.html out/index.html -cd out -cat <<-EOF | python - > versions.json -import os, json -print json.dumps([ - dir for dir in os.listdir(".") if not dir.startswith(".") and os.path.isdir(dir) -]) -EOF +echo "Making the versions.json file" +python ./util/versions.py out +cd out # Now let's go have some fun with the cloned repo git config user.name "GHA CI" git config user.email "gha@ci.invalid" diff --git a/util/versions.py b/util/versions.py new file mode 100755 index 000000000000..2c9bb5fe40a9 --- /dev/null +++ b/util/versions.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python + +import json +import os +import sys + +from lintlib import log + + +def key(v): + if v == 'master': + return float('inf') + if v == 'current': + return sys.maxsize + + v = v.replace('v', '').replace('rust-', '') + + s = 0 + for i, val in enumerate(v.split('.')[::-1]): + s += int(val) * 100**i + + return s + + +def main(): + if len(sys.argv) < 2: + print("Error: specify output directory") + return + + outdir = sys.argv[1] + versions = [ + dir for dir in os.listdir(outdir) if not dir.startswith(".") and os.path.isdir(os.path.join(outdir, dir)) + ] + versions.sort(key=key) + + with open(os.path.join(outdir, "versions.json"), "w") as fp: + json.dump(versions, fp, indent=2) + log.info("wrote JSON for great justice") + + +if __name__ == "__main__": + main() From 2044931cbe2ad7229eebd6cc044a73ad3dd244af Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 13 Feb 2020 17:32:29 +0100 Subject: [PATCH 076/243] Better version ordering of documentation --- util/gh-pages/versions.html | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/util/gh-pages/versions.html b/util/gh-pages/versions.html index 391e22a4743c..a1d385c965aa 100644 --- a/util/gh-pages/versions.html +++ b/util/gh-pages/versions.html @@ -36,7 +36,7 @@

@@ -54,10 +54,14 @@

.controller('docVersions', function ($scope, $http) { $scope.loading = true; - $scope.normalizeVersion = function(v) { + $scope.normalizeVersionDisplay = function(v) { return v.replace(/^v/, ''); }; + $scope.normalizeVersion = function(v) { + return v.replace(/^v/, '').replace(/^rust-/, ''); + }; + $scope.versionOrder = function(v) { if (v === 'master') { return Infinity; } if (v === 'current') { return Number.MAX_VALUE; } From 0533cff125d89e15bfda0a265ef01b1b33d8cd95 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 13 Feb 2020 18:07:56 +0100 Subject: [PATCH 077/243] Use python3 instead of python This changes the formatting a bit of json.dump(..) --- .github/deploy.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/deploy.sh b/.github/deploy.sh index 59a7cdae866e..8007bc75cddd 100644 --- a/.github/deploy.sh +++ b/.github/deploy.sh @@ -8,7 +8,7 @@ rm -rf out/master/ || exit 0 echo "Making the docs for master" mkdir out/master/ cp util/gh-pages/index.html out/master -python ./util/export.py out/master/lints.json +python3 ./util/export.py out/master/lints.json if [[ -n $TAG_NAME ]]; then echo "Save the doc for the current tag ($TAG_NAME) and point current/ to it" @@ -21,7 +21,7 @@ fi cp util/gh-pages/versions.html out/index.html echo "Making the versions.json file" -python ./util/versions.py out +python3 ./util/versions.py out cd out # Now let's go have some fun with the cloned repo From fa0ad30465032e2fccbd147ec441af8b6e61663c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 13 Feb 2020 22:01:26 +0100 Subject: [PATCH 078/243] deps: update pulldown-cmark from 0.6 to 0.7 --- clippy_lints/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index dae403cbb4f1..68a3204cbe42 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -22,7 +22,7 @@ if_chain = "1.0.0" itertools = "0.8" lazy_static = "1.0.2" matches = "0.1.7" -pulldown-cmark = "0.6.0" +pulldown-cmark = "0.7.0" quine-mc_cluskey = "0.2.2" regex-syntax = "0.6" serde = { version = "1.0", features = ["derive"] } From 0f7918266fa4f4a50237c8bdac79cb1e3001d86c Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 14 Feb 2020 12:03:48 +0100 Subject: [PATCH 079/243] Rename current -> stable --- .github/deploy.sh | 6 +++--- util/gh-pages/versions.html | 2 +- util/versions.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/deploy.sh b/.github/deploy.sh index 8007bc75cddd..b1f572d2b455 100644 --- a/.github/deploy.sh +++ b/.github/deploy.sh @@ -11,10 +11,10 @@ cp util/gh-pages/index.html out/master python3 ./util/export.py out/master/lints.json if [[ -n $TAG_NAME ]]; then - echo "Save the doc for the current tag ($TAG_NAME) and point current/ to it" + echo "Save the doc for the current tag ($TAG_NAME) and point stable/ to it" cp -r out/master "out/$TAG_NAME" - rm -f out/current - ln -s "$TAG_NAME" out/current + rm -f out/stable + ln -s "$TAG_NAME" out/stable fi # Generate version index that is shown as root index page diff --git a/util/gh-pages/versions.html b/util/gh-pages/versions.html index a1d385c965aa..cd3611db3005 100644 --- a/util/gh-pages/versions.html +++ b/util/gh-pages/versions.html @@ -64,7 +64,7 @@

$scope.versionOrder = function(v) { if (v === 'master') { return Infinity; } - if (v === 'current') { return Number.MAX_VALUE; } + if (v === 'stable') { return Number.MAX_VALUE; } return $scope.normalizeVersion(v) .split('.') diff --git a/util/versions.py b/util/versions.py index 2c9bb5fe40a9..5798761ad75b 100755 --- a/util/versions.py +++ b/util/versions.py @@ -10,7 +10,7 @@ def key(v): if v == 'master': return float('inf') - if v == 'current': + if v == 'stable': return sys.maxsize v = v.replace('v', '').replace('rust-', '') From 560559bafe1d61bca3d815ce80c53ae2d48e1829 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 11 Feb 2020 11:07:38 +0100 Subject: [PATCH 080/243] Make Lint::by_lint_group take impl Iterator as argument --- clippy_dev/src/lib.rs | 9 +++------ clippy_dev/src/main.rs | 4 ++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 3acecf967910..67a9abd29d67 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -63,11 +63,8 @@ impl Lint { /// Returns the lints in a `HashMap`, grouped by the different lint groups #[must_use] - pub fn by_lint_group(lints: &[Self]) -> HashMap> { - lints - .iter() - .map(|lint| (lint.group.to_string(), lint.clone())) - .into_group_map() + pub fn by_lint_group(lints: impl Iterator) -> HashMap> { + lints.map(|lint| (lint.group.to_string(), lint)).into_group_map() } #[must_use] @@ -449,7 +446,7 @@ fn test_by_lint_group() { "group2".to_string(), vec![Lint::new("should_assert_eq2", "group2", "abc", None, "module_name")], ); - assert_eq!(expected, Lint::by_lint_group(&lints)); + assert_eq!(expected, Lint::by_lint_group(lints.into_iter())); } #[test] diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 154876817429..2808aafc6905 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -136,7 +136,7 @@ fn print_lints() { let lint_list = gather_all(); let usable_lints: Vec = Lint::usable_lints(lint_list).collect(); let lint_count = usable_lints.len(); - let grouped_by_lint_group = Lint::by_lint_group(&usable_lints); + let grouped_by_lint_group = Lint::by_lint_group(usable_lints.into_iter()); for (lint_group, mut lints) in grouped_by_lint_group { if lint_group == "Deprecated" { @@ -267,7 +267,7 @@ fn update_lints(update_mode: UpdateMode) { .changed; // Generate the list of lints for all other lint groups - for (lint_group, lints) in Lint::by_lint_group(&usable_lints) { + for (lint_group, lints) in Lint::by_lint_group(usable_lints.into_iter()) { file_change |= replace_region_in_file( Path::new("clippy_lints/src/lib.rs"), &format!("store.register_group\\(true, \"clippy::{}\"", lint_group), From 3da2c9183a19c6f11e8bd61f16d03b6830eb3eec Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 11 Feb 2020 11:10:54 +0100 Subject: [PATCH 081/243] Save Lint::module as full path of module --- clippy_dev/src/lib.rs | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 67a9abd29d67..042ce9bc009b 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -170,29 +170,34 @@ pub fn gather_all() -> impl Iterator { fn gather_from_file(dir_entry: &walkdir::DirEntry) -> impl Iterator { let content = fs::read_to_string(dir_entry.path()).unwrap(); - let mut filename = dir_entry.path().file_stem().unwrap().to_str().unwrap(); + let path = dir_entry.path(); + let filename = path.file_stem().unwrap(); + let path_buf = path.with_file_name(filename); + let mut rel_path = path_buf + .strip_prefix(clippy_project_root().join("clippy_lints/src")) + .expect("only files in `clippy_lints/src` should be looked at"); // If the lints are stored in mod.rs, we get the module name from // the containing directory: if filename == "mod" { - filename = dir_entry - .path() - .parent() - .unwrap() - .file_stem() - .unwrap() - .to_str() - .unwrap() + rel_path = rel_path.parent().unwrap(); } - parse_contents(&content, filename) + + let module = rel_path + .components() + .map(|c| c.as_os_str().to_str().unwrap()) + .collect::>() + .join("::"); + + parse_contents(&content, &module) } -fn parse_contents(content: &str, filename: &str) -> impl Iterator { +fn parse_contents(content: &str, module: &str) -> impl Iterator { let lints = DEC_CLIPPY_LINT_RE .captures_iter(content) - .map(|m| Lint::new(&m["name"], &m["cat"], &m["desc"], None, filename)); + .map(|m| Lint::new(&m["name"], &m["cat"], &m["desc"], None, module)); let deprecated = DEC_DEPRECATED_LINT_RE .captures_iter(content) - .map(|m| Lint::new(&m["name"], "Deprecated", &m["desc"], Some(&m["desc"]), filename)); + .map(|m| Lint::new(&m["name"], "Deprecated", &m["desc"], Some(&m["desc"]), module)); // Removing the `.collect::>().into_iter()` causes some lifetime issues due to the map lints.chain(deprecated).collect::>().into_iter() } From 4a9bfe41841ad7299174832cbad450625ef5fc58 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 11 Feb 2020 11:11:43 +0100 Subject: [PATCH 082/243] Let update_lints also generate the internal lints --- clippy_dev/src/lib.rs | 7 ++++++- clippy_dev/src/main.rs | 4 +++- clippy_lints/src/lib.rs | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 042ce9bc009b..8e6479b64c4c 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -61,6 +61,11 @@ impl Lint { lints.filter(|l| l.deprecation.is_none() && !l.is_internal()) } + /// Returns all internal lints (not `internal_warn` lints) + pub fn internal_lints(lints: impl Iterator) -> impl Iterator { + lints.filter(|l| l.group == "internal") + } + /// Returns the lints in a `HashMap`, grouped by the different lint groups #[must_use] pub fn by_lint_group(lints: impl Iterator) -> HashMap> { @@ -79,7 +84,7 @@ pub fn gen_lint_group_list(lints: Vec) -> Vec { lints .into_iter() .filter_map(|l| { - if l.is_internal() || l.deprecation.is_some() { + if l.deprecation.is_some() { None } else { Some(format!(" LintId::of(&{}::{}),", l.module, l.name.to_uppercase())) diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 2808aafc6905..c2c9112e3b86 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -164,6 +164,8 @@ fn print_lints() { fn update_lints(update_mode: UpdateMode) { let lint_list: Vec = gather_all().collect(); + let internal_lints = Lint::internal_lints(lint_list.clone().into_iter()); + let usable_lints: Vec = Lint::usable_lints(lint_list.clone().into_iter()).collect(); let lint_count = usable_lints.len(); @@ -267,7 +269,7 @@ fn update_lints(update_mode: UpdateMode) { .changed; // Generate the list of lints for all other lint groups - for (lint_group, lints) in Lint::by_lint_group(usable_lints.into_iter()) { + for (lint_group, lints) in Lint::by_lint_group(usable_lints.into_iter().chain(internal_lints)) { file_change |= replace_region_in_file( Path::new("clippy_lints/src/lib.rs"), &format!("store.register_group\\(true, \"clippy::{}\"", lint_group), diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 02cf2d06f04d..a641ff777871 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1105,10 +1105,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_group(true, "clippy::internal", Some("clippy_internal"), vec![ LintId::of(&utils::internal_lints::CLIPPY_LINTS_INTERNAL), LintId::of(&utils::internal_lints::COMPILER_LINT_FUNCTIONS), + LintId::of(&utils::internal_lints::DEFAULT_LINT), LintId::of(&utils::internal_lints::LINT_WITHOUT_LINT_PASS), LintId::of(&utils::internal_lints::OUTER_EXPN_EXPN_DATA), LintId::of(&utils::internal_lints::PRODUCE_ICE), - LintId::of(&utils::internal_lints::DEFAULT_LINT), ]); store.register_group(true, "clippy::all", Some("clippy"), vec![ From 2635a602bc62928fc44b3c7d7c439eb4c788f552 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 11 Feb 2020 11:29:03 +0100 Subject: [PATCH 083/243] Update some documentation --- doc/adding_lints.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/adding_lints.md b/doc/adding_lints.md index cc4b5f7d1623..7e1263ebf22f 100644 --- a/doc/adding_lints.md +++ b/doc/adding_lints.md @@ -191,15 +191,15 @@ declare_lint_pass!(FooFunctions => [FOO_FUNCTIONS]); impl EarlyLintPass for FooFunctions {} ``` -Don't worry about the `name` method here. As long as it includes the name of the -lint pass it should be fine. - -The new lint automation runs `update_lints`, which automates some things, but it -doesn't automate everything. We will have to register our lint pass manually in -the `register_plugins` function in `clippy_lints/src/lib.rs`: +Normally after declaring the lint, we have to run `cargo dev update_lints`, +which updates some files, so Clippy knows about the new lint. Since we used +`cargo dev new_lint ...` to generate the lint declaration, this was done +automatically. While `update_lints` automates most of the things, it doesn't +automate everything. We will have to register our lint pass manually in the +`register_plugins` function in `clippy_lints/src/lib.rs`: ```rust -reg.register_early_lint_pass(box foo_functions::FooFunctions); +store.register_early_pass(box foo_functions::FooFunctions); ``` This should fix the `unknown clippy lint: clippy::foo_functions` error that we From 07026983f5e46ac5c5caf2dc86014a83297a0c4f Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 12 Feb 2020 09:12:19 +0100 Subject: [PATCH 084/243] Rename lint_count -> usable_lint_count --- clippy_dev/src/main.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index c2c9112e3b86..ec0c33109ba9 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -135,7 +135,7 @@ fn main() { fn print_lints() { let lint_list = gather_all(); let usable_lints: Vec = Lint::usable_lints(lint_list).collect(); - let lint_count = usable_lints.len(); + let usable_lint_count = usable_lints.len(); let grouped_by_lint_group = Lint::by_lint_group(usable_lints.into_iter()); for (lint_group, mut lints) in grouped_by_lint_group { @@ -157,7 +157,7 @@ fn print_lints() { } } - println!("there are {} lints", lint_count); + println!("there are {} lints", usable_lint_count); } #[allow(clippy::too_many_lines)] @@ -167,7 +167,7 @@ fn update_lints(update_mode: UpdateMode) { let internal_lints = Lint::internal_lints(lint_list.clone().into_iter()); let usable_lints: Vec = Lint::usable_lints(lint_list.clone().into_iter()).collect(); - let lint_count = usable_lints.len(); + let usable_lint_count = usable_lints.len(); let mut sorted_usable_lints = usable_lints.clone(); sorted_usable_lints.sort_by_key(|lint| lint.name.clone()); @@ -200,7 +200,7 @@ fn update_lints(update_mode: UpdateMode) { || { vec![format!( "[There are {} lints included in this crate!]({})", - lint_count, DOCS_LINK + usable_lint_count, DOCS_LINK )] }, ) From 50a2f971fcfb1156dd6bad37f88ba7e651390714 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 14 Feb 2020 14:42:24 +0100 Subject: [PATCH 085/243] Adapt gen_lint_group_list test to also generate internal lints --- clippy_dev/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 8e6479b64c4c..6fe7bb155ac5 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -529,10 +529,11 @@ fn test_gen_lint_group_list() { Lint::new("abc", "group1", "abc", None, "module_name"), Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), Lint::new("should_assert_eq2", "group2", "abc", Some("abc"), "deprecated"), - Lint::new("incorrect_internal", "internal_style", "abc", None, "module_name"), + Lint::new("internal", "internal_style", "abc", None, "module_name"), ]; let expected = vec![ " LintId::of(&module_name::ABC),".to_string(), + " LintId::of(&module_name::INTERNAL),".to_string(), " LintId::of(&module_name::SHOULD_ASSERT_EQ),".to_string(), ]; assert_eq!(expected, gen_lint_group_list(lints)); From 787398aa53ef633d67433e6e89c14590b54fa4af Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 15 Feb 2020 16:24:49 +0000 Subject: [PATCH 086/243] Avoid using regions from `TypeckTables` These regions will all be `ReErased` soon. --- clippy_lints/src/methods/mod.rs | 39 ++++++++++++++++++++-- clippy_lints/src/needless_pass_by_value.rs | 4 +-- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 716cd74ab92f..d84948654771 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1721,14 +1721,49 @@ fn lint_expect_fun_call( if match_type(cx, arg_ty, &paths::STRING) { return false; } - if let ty::Ref(ty::ReStatic, ty, ..) = arg_ty.kind { - if ty.kind == ty::Str { + if let ty::Ref(_, ty, ..) = arg_ty.kind { + if ty.kind == ty::Str && can_be_static_str(cx, arg) { return false; } }; true } + // Check if an expression could have type `&'static str`, knowing that it + // has type `&str` for some lifetime. + fn can_be_static_str(cx: &LateContext<'_, '_>, arg: &hir::Expr<'_>) -> bool { + match arg.kind { + hir::ExprKind::Lit(_) => true, + hir::ExprKind::Call(fun, _) => { + if let hir::ExprKind::Path(ref p) = fun.kind { + match cx.tables.qpath_res(p, fun.hir_id) { + hir::def::Res::Def(hir::def::DefKind::Fn, def_id) + | hir::def::Res::Def(hir::def::DefKind::Method, def_id) => matches!( + cx.tcx.fn_sig(def_id).output().skip_binder().kind, + ty::Ref(ty::ReStatic, ..) + ), + _ => false, + } + } else { + false + } + }, + hir::ExprKind::MethodCall(..) => cx.tables.type_dependent_def_id(arg.hir_id).map_or(false, |method_id| { + matches!( + cx.tcx.fn_sig(method_id).output().skip_binder().kind, + ty::Ref(ty::ReStatic, ..) + ) + }), + hir::ExprKind::Path(ref p) => match cx.tables.qpath_res(p, arg.hir_id) { + hir::def::Res::Def(hir::def::DefKind::Const, _) | hir::def::Res::Def(hir::def::DefKind::Static, _) => { + true + }, + _ => false, + }, + _ => false, + } + } + fn generate_format_arg_snippet( cx: &LateContext<'_, '_>, a: &hir::Expr<'_>, diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 0e844b920712..7bf7f21dd54e 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -7,7 +7,7 @@ use if_chain::if_chain; use matches::matches; use rustc::traits; use rustc::traits::misc::can_type_implement_copy; -use rustc::ty::{self, RegionKind, TypeFoldable}; +use rustc::ty::{self, TypeFoldable}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir::intravisit::FnKind; @@ -171,7 +171,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { ( preds.iter().any(|t| t.def_id() == borrow_trait), !preds.is_empty() && { - let ty_empty_region = cx.tcx.mk_imm_ref(&RegionKind::ReEmpty(ty::UniverseIndex::ROOT), ty); + let ty_empty_region = cx.tcx.mk_imm_ref(cx.tcx.lifetimes.re_root_empty, ty); preds.iter().all(|t| { let ty_params = &t .skip_binder() From 4480ec5b71c4fb1c58cf5235217cf61df88bd73d Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 17 Feb 2020 11:07:26 +0900 Subject: [PATCH 087/243] Rustup to rust-lang/rust#67953 --- clippy_lints/src/escape.rs | 1 + clippy_lints/src/len_zero.rs | 2 +- clippy_lints/src/lib.rs | 2 ++ clippy_lints/src/loops.rs | 1 + clippy_lints/src/needless_pass_by_value.rs | 5 +++-- clippy_lints/src/utils/mod.rs | 3 ++- clippy_lints/src/utils/usage.rs | 1 + 7 files changed, 11 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 6d0a1f673e77..ec1d3a24f036 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -3,6 +3,7 @@ use rustc::ty::{self, Ty}; use rustc_hir::intravisit as visit; use rustc_hir::HirIdSet; use rustc_hir::{self, *}; +use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 2d381148012c..b1ed88f59d4a 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -134,7 +134,7 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item<'_>, trait_i // fill the set with current and super traits fn fill_trait_set(traitt: DefId, set: &mut FxHashSet, cx: &LateContext<'_, '_>) { if set.insert(traitt) { - for supertrait in rustc::traits::supertrait_def_ids(cx.tcx, traitt) { + for supertrait in rustc_infer::traits::supertrait_def_ids(cx.tcx, traitt) { fill_trait_set(supertrait, set, cx); } } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a641ff777871..1cf01d2e02e5 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -33,6 +33,8 @@ extern crate rustc_hir; #[allow(unused_extern_crates)] extern crate rustc_index; #[allow(unused_extern_crates)] +extern crate rustc_infer; +#[allow(unused_extern_crates)] extern crate rustc_lexer; #[allow(unused_extern_crates)] extern crate rustc_lint; diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 1aea630efe4e..3eee2728ce2c 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -21,6 +21,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id; use rustc_hir::intravisit::{walk_block, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; use rustc_hir::*; +use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 7bf7f21dd54e..7a0f3bdd3558 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -5,13 +5,14 @@ use crate::utils::{ }; use if_chain::if_chain; use matches::matches; -use rustc::traits; -use rustc::traits::misc::can_type_implement_copy; use rustc::ty::{self, TypeFoldable}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir::intravisit::FnKind; use rustc_hir::*; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits; +use rustc_infer::traits::misc::can_type_implement_copy; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{Span, Symbol}; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index ed6d9f81cc9f..b13648afda9e 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -27,7 +27,6 @@ use if_chain::if_chain; use matches::matches; use rustc::hir::map::Map; use rustc::traits; -use rustc::traits::predicate_for_trait_def; use rustc::ty::{ self, layout::{self, IntegerExt}, @@ -42,6 +41,8 @@ use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::intravisit::{NestedVisitorMap, Visitor}; use rustc_hir::Node; use rustc_hir::*; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits::predicate_for_trait_def; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::original_sp; diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs index 7939d7d0863c..8fff1c7a16cb 100644 --- a/clippy_lints/src/utils/usage.rs +++ b/clippy_lints/src/utils/usage.rs @@ -5,6 +5,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::*; +use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_span::symbol::Ident; use rustc_typeck::expr_use_visitor::*; From 09165ff5761bb1f397e37ee2d32d96adf7afdd86 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 17 Feb 2020 05:44:38 +0900 Subject: [PATCH 088/243] Don't lint `single_component_path_imports` in macros --- clippy_lints/src/single_component_path_imports.rs | 3 ++- tests/ui/single_component_path_imports.fixed | 9 +++++++++ tests/ui/single_component_path_imports.rs | 9 +++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/single_component_path_imports.rs b/clippy_lints/src/single_component_path_imports.rs index eb3261bebe31..5a9bc73fe42b 100644 --- a/clippy_lints/src/single_component_path_imports.rs +++ b/clippy_lints/src/single_component_path_imports.rs @@ -1,4 +1,4 @@ -use crate::utils::span_lint_and_sugg; +use crate::utils::{in_macro, span_lint_and_sugg}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; @@ -39,6 +39,7 @@ declare_lint_pass!(SingleComponentPathImports => [SINGLE_COMPONENT_PATH_IMPORTS] impl EarlyLintPass for SingleComponentPathImports { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { if_chain! { + if !in_macro(item.span); if cx.sess.opts.edition == Edition::Edition2018; if !item.vis.node.is_pub(); if let ItemKind::Use(use_tree) = &item.kind; diff --git a/tests/ui/single_component_path_imports.fixed b/tests/ui/single_component_path_imports.fixed index 7a882efc4d18..9095069b0939 100644 --- a/tests/ui/single_component_path_imports.fixed +++ b/tests/ui/single_component_path_imports.fixed @@ -7,6 +7,15 @@ use serde as edres; pub use serde; +macro_rules! m { + () => { + use regex; + }; +} + fn main() { regex::Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap(); + + // False positive #5154, shouldn't trigger lint. + m!(); } diff --git a/tests/ui/single_component_path_imports.rs b/tests/ui/single_component_path_imports.rs index d084425cd70f..1ebb3ee59b8b 100644 --- a/tests/ui/single_component_path_imports.rs +++ b/tests/ui/single_component_path_imports.rs @@ -7,6 +7,15 @@ use regex; use serde as edres; pub use serde; +macro_rules! m { + () => { + use regex; + }; +} + fn main() { regex::Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap(); + + // False positive #5154, shouldn't trigger lint. + m!(); } From d488218ec12bfa174c0a8ba0a92df26b2b51736f Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 17 Feb 2020 13:39:48 +0900 Subject: [PATCH 089/243] Reduce pulldown-cmark size --- clippy_lints/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 68a3204cbe42..ad3b077ec4b9 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -22,7 +22,7 @@ if_chain = "1.0.0" itertools = "0.8" lazy_static = "1.0.2" matches = "0.1.7" -pulldown-cmark = "0.7.0" +pulldown-cmark = { version = "0.7", default-features = false } quine-mc_cluskey = "0.2.2" regex-syntax = "0.6" serde = { version = "1.0", features = ["derive"] } From 0532f3e521293d4fa01518a238ea61665b11a3aa Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Sun, 16 Feb 2020 23:48:10 -0800 Subject: [PATCH 090/243] Add lint to detect lossy float literals --- clippy_lints/src/excessive_precision.rs | 115 +++++++++++------------- 1 file changed, 52 insertions(+), 63 deletions(-) diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index 2b63d5e9088e..70b44dee6619 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -6,17 +6,15 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::symbol::Symbol; -use std::f32; -use std::f64; -use std::fmt; +use std::{f32, f64, fmt}; use syntax::ast::*; declare_clippy_lint! { /// **What it does:** Checks for float literals with a precision greater - /// than that supported by the underlying type + /// than that supported by the underlying type. /// - /// **Why is this bad?** Rust will truncate the literal silently. + /// **Why is this bad?** Rust will silently lose precision during conversion + /// to a float. /// /// **Known problems:** None. /// @@ -44,71 +42,62 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision { let ty = cx.tables.expr_ty(expr); if let ty::Float(fty) = ty.kind; if let hir::ExprKind::Lit(ref lit) = expr.kind; - if let LitKind::Float(sym, _) = lit.node; - if let Some(sugg) = Self::check(sym, fty); + if let LitKind::Float(sym, lit_float_ty) = lit.node; then { - span_lint_and_sugg( - cx, - EXCESSIVE_PRECISION, - expr.span, - "float has excessive precision", - "consider changing the type or truncating it to", - sugg, - Applicability::MachineApplicable, - ); - } - } - } -} - -impl ExcessivePrecision { - // None if nothing to lint, Some(suggestion) if lint necessary - #[must_use] - fn check(sym: Symbol, fty: FloatTy) -> Option { - let max = max_digits(fty); - let sym_str = sym.as_str(); - if dot_zero_exclusion(&sym_str) { - return None; - } - // Try to bail out if the float is for sure fine. - // If its within the 2 decimal digits of being out of precision we - // check if the parsed representation is the same as the string - // since we'll need the truncated string anyway. - let digits = count_digits(&sym_str); - if digits > max as usize { - let formatter = FloatFormat::new(&sym_str); - let sr = match fty { - FloatTy::F32 => sym_str.parse::().map(|f| formatter.format(f)), - FloatTy::F64 => sym_str.parse::().map(|f| formatter.format(f)), - }; - // We know this will parse since we are in LatePass - let s = sr.unwrap(); + let sym_str = sym.as_str(); + let formatter = FloatFormat::new(&sym_str); + // Try to bail out if the float is for sure fine. + // If its within the 2 decimal digits of being out of precision we + // check if the parsed representation is the same as the string + // since we'll need the truncated string anyway. + let digits = count_digits(&sym_str); + let max = max_digits(fty); + let float_str = match fty { + FloatTy::F32 => sym_str.parse::().map(|f| formatter.format(f)), + FloatTy::F64 => sym_str.parse::().map(|f| formatter.format(f)), + }.unwrap(); + let type_suffix = match lit_float_ty { + LitFloatType::Suffixed(FloatTy::F32) => Some("f32"), + LitFloatType::Suffixed(FloatTy::F64) => Some("f64"), + _ => None + }; - if sym_str == s { - None - } else { - Some(format_numeric_literal(&s, None, true)) + if is_whole_number(&sym_str, fty) { + // Normalize the literal by stripping the fractional portion + if sym_str.split('.').next().unwrap() != float_str { + span_lint_and_sugg( + cx, + EXCESSIVE_PRECISION, + expr.span, + "literal cannot be represented as the underlying type without loss of precision", + "consider changing the type or replacing it with", + format_numeric_literal(format!("{}.0", float_str).as_str(), type_suffix, true), + Applicability::MachineApplicable, + ); + } + } else if digits > max as usize && sym_str != float_str { + span_lint_and_sugg( + cx, + EXCESSIVE_PRECISION, + expr.span, + "float has excessive precision", + "consider changing the type or truncating it to", + format_numeric_literal(&float_str, type_suffix, true), + Applicability::MachineApplicable, + ); + } } - } else { - None } } } -/// Should we exclude the float because it has a `.0` or `.` suffix -/// Ex `1_000_000_000.0` -/// Ex `1_000_000_000.` +// Checks whether a float literal is a whole number #[must_use] -fn dot_zero_exclusion(s: &str) -> bool { - s.split('.').nth(1).map_or(false, |after_dec| { - let mut decpart = after_dec.chars().take_while(|c| *c != 'e' || *c != 'E'); - - match decpart.next() { - Some('0') => decpart.count() == 0, - Some(_) => false, - None => true, - } - }) +fn is_whole_number(sym_str: &str, fty: FloatTy) -> bool { + match fty { + FloatTy::F32 => sym_str.parse::().unwrap().fract() == 0.0, + FloatTy::F64 => sym_str.parse::().unwrap().fract() == 0.0, + } } #[must_use] From 552452873ce393a0543de7d1cb6356dc0888d551 Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Sun, 16 Feb 2020 23:55:16 -0800 Subject: [PATCH 091/243] Add tests for lossy whole number float literals --- tests/ui/excessive_precision.fixed | 32 ++++++++++-- tests/ui/excessive_precision.rs | 22 ++++++++ tests/ui/excessive_precision.stderr | 78 ++++++++++++++++++++++++++--- 3 files changed, 121 insertions(+), 11 deletions(-) diff --git a/tests/ui/excessive_precision.fixed b/tests/ui/excessive_precision.fixed index 1646dff9064d..f32307ce9107 100644 --- a/tests/ui/excessive_precision.fixed +++ b/tests/ui/excessive_precision.fixed @@ -12,12 +12,12 @@ fn main() { const GOOD64_SM: f32 = 0.000_000_000_000_000_1; const GOOD64_DOT: f32 = 10_000_000_000_000_000.0; - const BAD32_1: f32 = 0.123_456_79; + const BAD32_1: f32 = 0.123_456_79_f32; const BAD32_2: f32 = 0.123_456_79; const BAD32_3: f32 = 0.1; const BAD32_EDGE: f32 = 1.000_001; - const BAD64_1: f64 = 0.123_456_789_012_345_66; + const BAD64_1: f64 = 0.123_456_789_012_345_66_f64; const BAD64_2: f64 = 0.123_456_789_012_345_66; const BAD64_3: f64 = 0.1; @@ -34,11 +34,11 @@ fn main() { let good64_inf = 0.123_456_789_012; let bad32: f32 = 1.123_456_8; - let bad32_suf: f32 = 1.123_456_8; - let bad32_inf = 1.123_456_8; + let bad32_suf: f32 = 1.123_456_8_f32; + let bad32_inf = 1.123_456_8_f32; let bad64: f64 = 0.123_456_789_012_345_66; - let bad64_suf: f64 = 0.123_456_789_012_345_66; + let bad64_suf: f64 = 0.123_456_789_012_345_66_f64; let bad64_inf = 0.123_456_789_012_345_66; // Vectors @@ -60,4 +60,26 @@ fn main() { // issue #2840 let num = 0.000_000_000_01e-10f64; + + // Lossy whole-number float literals + let _: f32 = 16_777_216.0; + let _: f32 = 16_777_220.0; + let _: f32 = 16_777_220.0; + let _: f32 = 16_777_220.0; + let _ = 16_777_220.0_f32; + let _: f32 = -16_777_220.0; + let _: f64 = 9_007_199_254_740_992.0; + let _: f64 = 9_007_199_254_740_992.0; + let _: f64 = 9_007_199_254_740_992.0; + let _ = 9_007_199_254_740_992.0_f64; + let _: f64 = -9_007_199_254_740_992.0; + + // Lossless whole number float literals + let _: f32 = 16_777_216.0; + let _: f32 = 16_777_218.0; + let _: f32 = 16_777_220.0; + let _: f32 = -16_777_216.0; + let _: f32 = -16_777_220.0; + let _: f64 = 9_007_199_254_740_992.0; + let _: f64 = -9_007_199_254_740_992.0; } diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index ce4722a90f90..a3d317400278 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -60,4 +60,26 @@ fn main() { // issue #2840 let num = 0.000_000_000_01e-10f64; + + // Lossy whole-number float literals + let _: f32 = 16_777_217.0; + let _: f32 = 16_777_219.0; + let _: f32 = 16_777_219.; + let _: f32 = 16_777_219.000; + let _ = 16_777_219f32; + let _: f32 = -16_777_219.0; + let _: f64 = 9_007_199_254_740_993.0; + let _: f64 = 9_007_199_254_740_993.; + let _: f64 = 9_007_199_254_740_993.000; + let _ = 9_007_199_254_740_993f64; + let _: f64 = -9_007_199_254_740_993.0; + + // Lossless whole number float literals + let _: f32 = 16_777_216.0; + let _: f32 = 16_777_218.0; + let _: f32 = 16_777_220.0; + let _: f32 = -16_777_216.0; + let _: f32 = -16_777_220.0; + let _: f64 = 9_007_199_254_740_992.0; + let _: f64 = -9_007_199_254_740_992.0; } diff --git a/tests/ui/excessive_precision.stderr b/tests/ui/excessive_precision.stderr index 12f8a61b75c5..8941bcfd86d8 100644 --- a/tests/ui/excessive_precision.stderr +++ b/tests/ui/excessive_precision.stderr @@ -2,7 +2,7 @@ error: float has excessive precision --> $DIR/excessive_precision.rs:15:26 | LL | const BAD32_1: f32 = 0.123_456_789_f32; - | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` + | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79_f32` | = note: `-D clippy::excessive-precision` implied by `-D warnings` @@ -28,7 +28,7 @@ error: float has excessive precision --> $DIR/excessive_precision.rs:20:26 | LL | const BAD64_1: f64 = 0.123_456_789_012_345_67f64; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66_f64` error: float has excessive precision --> $DIR/excessive_precision.rs:21:26 @@ -58,13 +58,13 @@ error: float has excessive precision --> $DIR/excessive_precision.rs:37:26 | LL | let bad32_suf: f32 = 1.123_456_789_f32; - | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` + | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8_f32` error: float has excessive precision --> $DIR/excessive_precision.rs:38:21 | LL | let bad32_inf = 1.123_456_789_f32; - | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` + | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8_f32` error: float has excessive precision --> $DIR/excessive_precision.rs:40:22 @@ -76,7 +76,7 @@ error: float has excessive precision --> $DIR/excessive_precision.rs:41:26 | LL | let bad64_suf: f64 = 0.123_456_789_012_345_67f64; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_012_345_66_f64` error: float has excessive precision --> $DIR/excessive_precision.rs:42:21 @@ -108,5 +108,71 @@ error: float has excessive precision LL | let bad_bige32: f32 = 1.123_456_788_888E-10; | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8E-10` -error: aborting due to 18 previous errors +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/excessive_precision.rs:65:18 + | +LL | let _: f32 = 16_777_217.0; + | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_216.0` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/excessive_precision.rs:66:18 + | +LL | let _: f32 = 16_777_219.0; + | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/excessive_precision.rs:67:18 + | +LL | let _: f32 = 16_777_219.; + | ^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/excessive_precision.rs:68:18 + | +LL | let _: f32 = 16_777_219.000; + | ^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/excessive_precision.rs:69:13 + | +LL | let _ = 16_777_219f32; + | ^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0_f32` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/excessive_precision.rs:70:19 + | +LL | let _: f32 = -16_777_219.0; + | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/excessive_precision.rs:71:18 + | +LL | let _: f64 = 9_007_199_254_740_993.0; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/excessive_precision.rs:72:18 + | +LL | let _: f64 = 9_007_199_254_740_993.; + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/excessive_precision.rs:73:18 + | +LL | let _: f64 = 9_007_199_254_740_993.000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/excessive_precision.rs:74:13 + | +LL | let _ = 9_007_199_254_740_993f64; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0_f64` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/excessive_precision.rs:75:19 + | +LL | let _: f64 = -9_007_199_254_740_993.0; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` + +error: aborting due to 29 previous errors From 45936a6e26ad123bfaa391791edeb2c7f51b296c Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Mon, 17 Feb 2020 00:17:26 -0800 Subject: [PATCH 092/243] Uplift `excessive_precision` to the correctness category --- clippy_lints/src/excessive_precision.rs | 10 +++++----- clippy_lints/src/lib.rs | 2 +- src/lintlist/mod.rs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index 70b44dee6619..781d85a00e4f 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -22,15 +22,15 @@ declare_clippy_lint! { /// /// ```rust /// // Bad - /// let v: f32 = 0.123_456_789_9; - /// println!("{}", v); // 0.123_456_789 + /// let a: f32 = 0.123_456_789_9; // 0.123_456_789 + /// let b: f32 = 16_777_217.0; // 16_777_216.0 /// /// // Good - /// let v: f64 = 0.123_456_789_9; - /// println!("{}", v); // 0.123_456_789_9 + /// let a: f64 = 0.123_456_789_9; + /// let b: f64 = 16_777_216.0; /// ``` pub EXCESSIVE_PRECISION, - style, + correctness, "excessive precision for float literal" } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1cf01d2e02e5..8bd0d187061a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1386,7 +1386,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&enum_variants::MODULE_INCEPTION), LintId::of(&eq_op::OP_REF), LintId::of(&eta_reduction::REDUNDANT_CLOSURE), - LintId::of(&excessive_precision::EXCESSIVE_PRECISION), LintId::of(&formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING), LintId::of(&formatting::SUSPICIOUS_ELSE_FORMATTING), LintId::of(&formatting::SUSPICIOUS_UNARY_OP_FORMATTING), @@ -1567,6 +1566,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT), LintId::of(&eq_op::EQ_OP), LintId::of(&erasing_op::ERASING_OP), + LintId::of(&excessive_precision::EXCESSIVE_PRECISION), LintId::of(&formatting::POSSIBLE_MISSING_COMMA), LintId::of(&functions::NOT_UNSAFE_PTR_ARG_DEREF), LintId::of(&indexing_slicing::OUT_OF_BOUNDS_INDEXING), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 06a1fca4fdd8..8c04afce1d27 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -492,7 +492,7 @@ pub const ALL_LINTS: [Lint; 355] = [ }, Lint { name: "excessive_precision", - group: "style", + group: "correctness", desc: "excessive precision for float literal", deprecation: None, module: "excessive_precision", From f56e8b7eb47402056b851b11203acfa0994bc8e0 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 17 Feb 2020 18:36:17 +0900 Subject: [PATCH 093/243] Rename `FunctionRetTy` to `FnRetTy` --- clippy_lints/src/functions.rs | 4 ++-- clippy_lints/src/lifetimes.rs | 2 +- clippy_lints/src/methods/mod.rs | 12 ++++++------ clippy_lints/src/ptr.rs | 2 +- clippy_lints/src/returns.rs | 2 +- clippy_lints/src/types.rs | 4 ++-- clippy_lints/src/use_self.rs | 2 +- clippy_lints/src/utils/hir_utils.rs | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index ee9221c811e8..ce0bfea5160e 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -468,8 +468,8 @@ fn check_must_use_candidate<'a, 'tcx>( fn returns_unit(decl: &hir::FnDecl<'_>) -> bool { match decl.output { - hir::FunctionRetTy::DefaultReturn(_) => true, - hir::FunctionRetTy::Return(ref ty) => match ty.kind { + hir::FnRetTy::DefaultReturn(_) => true, + hir::FnRetTy::Return(ref ty) => match ty.kind { hir::TyKind::Tup(ref tys) => tys.is_empty(), hir::TyKind::Never => true, _ => false, diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 13484ba0fa76..f98021bca459 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -4,7 +4,7 @@ use rustc::lint::in_external_macro; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::*; -use rustc_hir::FunctionRetTy::Return; +use rustc_hir::FnRetTy::Return; use rustc_hir::*; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index d84948654771..00a9fd894647 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3406,14 +3406,14 @@ enum OutType { } impl OutType { - fn matches(self, cx: &LateContext<'_, '_>, ty: &hir::FunctionRetTy<'_>) -> bool { + fn matches(self, cx: &LateContext<'_, '_>, ty: &hir::FnRetTy<'_>) -> bool { let is_unit = |ty: &hir::Ty<'_>| SpanlessEq::new(cx).eq_ty_kind(&ty.kind, &hir::TyKind::Tup(&[])); match (self, ty) { - (Self::Unit, &hir::FunctionRetTy::DefaultReturn(_)) => true, - (Self::Unit, &hir::FunctionRetTy::Return(ref ty)) if is_unit(ty) => true, - (Self::Bool, &hir::FunctionRetTy::Return(ref ty)) if is_bool(ty) => true, - (Self::Any, &hir::FunctionRetTy::Return(ref ty)) if !is_unit(ty) => true, - (Self::Ref, &hir::FunctionRetTy::Return(ref ty)) => matches!(ty.kind, hir::TyKind::Rptr(_, _)), + (Self::Unit, &hir::FnRetTy::DefaultReturn(_)) => true, + (Self::Unit, &hir::FnRetTy::Return(ref ty)) if is_unit(ty) => true, + (Self::Bool, &hir::FnRetTy::Return(ref ty)) if is_bool(ty) => true, + (Self::Any, &hir::FnRetTy::Return(ref ty)) if !is_unit(ty) => true, + (Self::Ref, &hir::FnRetTy::Return(ref ty)) => matches!(ty.kind, hir::TyKind::Rptr(_, _)), _ => false, } } diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 445f065aaced..33cfa5d75c62 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -253,7 +253,7 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_ } } - if let FunctionRetTy::Return(ref ty) = decl.output { + if let FnRetTy::Return(ref ty) = decl.output { if let Some((out, Mutability::Mut, _)) = get_rptr_lm(ty) { let mut immutables = vec![]; for (_, ref mutbl, ref argspan) in decl diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 6bf373a9a626..fc371dccd732 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -242,7 +242,7 @@ impl EarlyLintPass for Return { FnKind::Fn(.., None) => {}, } if_chain! { - if let ast::FunctionRetTy::Ty(ref ty) = kind.decl().output; + if let ast::FnRetTy::Ty(ref ty) = kind.decl().output; if let ast::TyKind::Tup(ref vals) = ty.kind; if vals.is_empty() && !ty.span.from_expansion() && get_def(span) == get_def(ty.span); then { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index e47f2480a541..d23487b5b334 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -242,7 +242,7 @@ impl Types { self.check_ty(cx, input, false); } - if let FunctionRetTy::Return(ref ty) = decl.output { + if let FnRetTy::Return(ref ty) = decl.output { self.check_ty(cx, ty, false); } } @@ -1476,7 +1476,7 @@ impl<'a, 'tcx> TypeComplexity { for arg in decl.inputs { self.check_type(cx, arg); } - if let FunctionRetTy::Return(ref ty) = decl.output { + if let FnRetTy::Return(ref ty) = decl.output { self.check_type(cx, ty); } } diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 9be070bd3d15..da961a5f89da 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -141,7 +141,7 @@ fn check_trait_method_impl_decl<'a, 'tcx>( let impl_method_sig = cx.tcx.fn_sig(impl_method_def_id); let impl_method_sig = cx.tcx.erase_late_bound_regions(&impl_method_sig); - let output_ty = if let FunctionRetTy::Return(ty) = &impl_decl.output { + let output_ty = if let FnRetTy::Return(ty) = &impl_decl.output { Some(&**ty) } else { None diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index c209ebaaf137..f5f35afa9baa 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -633,10 +633,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_ty(&arg); } match bfn.decl.output { - FunctionRetTy::DefaultReturn(_) => { + FnRetTy::DefaultReturn(_) => { ().hash(&mut self.s); }, - FunctionRetTy::Return(ref ty) => { + FnRetTy::Return(ref ty) => { self.hash_ty(ty); }, } From 0b168c693a7c9e1307b143937d6537b36b929303 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sun, 16 Feb 2020 22:49:47 +0100 Subject: [PATCH 094/243] Add `Future` detection for `missing_errors_doc`. --- clippy_lints/src/doc.rs | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 5db1886bb52d..4b1f2ec68cb1 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -1,6 +1,7 @@ use crate::utils::{is_entrypoint_fn, match_type, paths, return_ty, span_lint}; use itertools::Itertools; use rustc::lint::in_external_macro; +use rustc::ty::TyKind; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; @@ -213,13 +214,33 @@ fn lint_for_missing_headers<'a, 'tcx>( "unsafe function's docs miss `# Safety` section", ); } - if !headers.errors && match_type(cx, return_ty(cx, hir_id), &paths::RESULT) { - span_lint( - cx, - MISSING_ERRORS_DOC, - span, - "docs for function returning `Result` missing `# Errors` section", - ); + if !headers.errors { + if match_type(cx, return_ty(cx, hir_id), &paths::RESULT) { + span_lint( + cx, + MISSING_ERRORS_DOC, + span, + "docs for function returning `Result` missing `# Errors` section", + ); + } else { + use TyKind::*; + let def_id = cx.tcx.hir().local_def_id(hir_id); + let mir = cx.tcx.optimized_mir(def_id); + if let Opaque(_, subs) = mir.return_ty().kind { + if let Some(ty) = subs.types().next() { + if let Generator(_, subs, _) = ty.kind { + if match_type(cx, subs.as_generator().return_ty(def_id, cx.tcx), &paths::RESULT) { + span_lint( + cx, + MISSING_ERRORS_DOC, + span, + "docs for function returning `Result` missing `# Errors` section", + ); + } + } + } + } + } } } From 0ee393cf01b59d55a54e9e4299797bd0f7339d58 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Mon, 17 Feb 2020 01:17:14 +0100 Subject: [PATCH 095/243] Add tests and improve checks. --- clippy_lints/src/doc.rs | 29 +++++++++++++++----------- clippy_lints/src/utils/paths.rs | 1 + tests/ui/doc_errors.rs | 37 +++++++++++++++++++++++++++++++++ tests/ui/doc_errors.stderr | 32 ++++++++++++++++++++++++---- 4 files changed, 83 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 4b1f2ec68cb1..133a20b669a1 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -1,4 +1,4 @@ -use crate::utils::{is_entrypoint_fn, match_type, paths, return_ty, span_lint}; +use crate::utils::{get_trait_def_id, implements_trait, is_entrypoint_fn, match_type, paths, return_ty, span_lint}; use itertools::Itertools; use rustc::lint::in_external_macro; use rustc::ty::TyKind; @@ -223,19 +223,24 @@ fn lint_for_missing_headers<'a, 'tcx>( "docs for function returning `Result` missing `# Errors` section", ); } else { - use TyKind::*; let def_id = cx.tcx.hir().local_def_id(hir_id); let mir = cx.tcx.optimized_mir(def_id); - if let Opaque(_, subs) = mir.return_ty().kind { - if let Some(ty) = subs.types().next() { - if let Generator(_, subs, _) = ty.kind { - if match_type(cx, subs.as_generator().return_ty(def_id, cx.tcx), &paths::RESULT) { - span_lint( - cx, - MISSING_ERRORS_DOC, - span, - "docs for function returning `Result` missing `# Errors` section", - ); + if let Some(future) = get_trait_def_id(cx, &paths::FUTURE) { + if implements_trait(cx, mir.return_ty(), future, &[]) { + use TyKind::*; + + if let Opaque(_, subs) = mir.return_ty().kind { + if let Some(ty) = subs.types().next() { + if let Generator(_, subs, _) = ty.kind { + if match_type(cx, subs.as_generator().return_ty(def_id, cx.tcx), &paths::RESULT) { + span_lint( + cx, + MISSING_ERRORS_DOC, + span, + "docs for function returning `Result` missing `# Errors` section", + ); + } + } } } } diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 0af7f946fa9d..96337e42b544 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -36,6 +36,7 @@ pub const FMT_ARGUMENTS_NEW_V1_FORMATTED: [&str; 4] = ["core", "fmt", "Arguments pub const FMT_ARGUMENTV1_NEW: [&str; 4] = ["core", "fmt", "ArgumentV1", "new"]; pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"]; pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"]; +pub const FUTURE: [&str; 3] = ["std", "future", "Future"]; pub const HASH: [&str; 2] = ["hash", "Hash"]; pub const HASHMAP: [&str; 5] = ["std", "collections", "hash", "map", "HashMap"]; pub const HASHMAP_ENTRY: [&str; 5] = ["std", "collections", "hash", "map", "Entry"]; diff --git a/tests/ui/doc_errors.rs b/tests/ui/doc_errors.rs index 776a65275e9b..1401a658e037 100644 --- a/tests/ui/doc_errors.rs +++ b/tests/ui/doc_errors.rs @@ -1,3 +1,4 @@ +// compile-flags: --edition 2018 #![warn(clippy::missing_errors_doc)] use std::io; @@ -6,22 +7,42 @@ pub fn pub_fn_missing_errors_header() -> Result<(), ()> { unimplemented!(); } +pub async fn async_pub_fn_missing_errors_header() -> Result<(), ()> { + unimplemented!(); +} + /// This is not sufficiently documented. pub fn pub_fn_returning_io_result() -> io::Result<()> { unimplemented!(); } +/// This is not sufficiently documented. +pub async fn async_pub_fn_returning_io_result() -> io::Result<()> { + unimplemented!(); +} + /// # Errors /// A description of the errors goes here. pub fn pub_fn_with_errors_header() -> Result<(), ()> { unimplemented!(); } +/// # Errors +/// A description of the errors goes here. +pub async fn async_pub_fn_with_errors_header() -> Result<(), ()> { + unimplemented!(); +} + /// This function doesn't require the documentation because it is private fn priv_fn_missing_errors_header() -> Result<(), ()> { unimplemented!(); } +/// This function doesn't require the documentation because it is private +async fn async_priv_fn_missing_errors_header() -> Result<(), ()> { + unimplemented!(); +} + pub struct Struct1; impl Struct1 { @@ -30,16 +51,32 @@ impl Struct1 { unimplemented!(); } + /// This is not sufficiently documented. + pub async fn async_pub_method_missing_errors_header() -> Result<(), ()> { + unimplemented!(); + } + /// # Errors /// A description of the errors goes here. pub fn pub_method_with_errors_header() -> Result<(), ()> { unimplemented!(); } + /// # Errors + /// A description of the errors goes here. + pub async fn async_pub_method_with_errors_header() -> Result<(), ()> { + unimplemented!(); + } + /// This function doesn't require the documentation because it is private. fn priv_method_missing_errors_header() -> Result<(), ()> { unimplemented!(); } + + /// This function doesn't require the documentation because it is private. + async fn async_priv_method_missing_errors_header() -> Result<(), ()> { + unimplemented!(); + } } pub trait Trait1 { diff --git a/tests/ui/doc_errors.stderr b/tests/ui/doc_errors.stderr index f1d321cf909c..f44d6693d303 100644 --- a/tests/ui/doc_errors.stderr +++ b/tests/ui/doc_errors.stderr @@ -1,5 +1,5 @@ error: docs for function returning `Result` missing `# Errors` section - --> $DIR/doc_errors.rs:5:1 + --> $DIR/doc_errors.rs:6:1 | LL | / pub fn pub_fn_missing_errors_header() -> Result<(), ()> { LL | | unimplemented!(); @@ -11,13 +11,29 @@ LL | | } error: docs for function returning `Result` missing `# Errors` section --> $DIR/doc_errors.rs:10:1 | +LL | / pub async fn async_pub_fn_missing_errors_header() -> Result<(), ()> { +LL | | unimplemented!(); +LL | | } + | |_^ + +error: docs for function returning `Result` missing `# Errors` section + --> $DIR/doc_errors.rs:15:1 + | LL | / pub fn pub_fn_returning_io_result() -> io::Result<()> { LL | | unimplemented!(); LL | | } | |_^ error: docs for function returning `Result` missing `# Errors` section - --> $DIR/doc_errors.rs:29:5 + --> $DIR/doc_errors.rs:20:1 + | +LL | / pub async fn async_pub_fn_returning_io_result() -> io::Result<()> { +LL | | unimplemented!(); +LL | | } + | |_^ + +error: docs for function returning `Result` missing `# Errors` section + --> $DIR/doc_errors.rs:50:5 | LL | / pub fn pub_method_missing_errors_header() -> Result<(), ()> { LL | | unimplemented!(); @@ -25,10 +41,18 @@ LL | | } | |_____^ error: docs for function returning `Result` missing `# Errors` section - --> $DIR/doc_errors.rs:47:5 + --> $DIR/doc_errors.rs:55:5 + | +LL | / pub async fn async_pub_method_missing_errors_header() -> Result<(), ()> { +LL | | unimplemented!(); +LL | | } + | |_____^ + +error: docs for function returning `Result` missing `# Errors` section + --> $DIR/doc_errors.rs:84:5 | LL | fn trait_method_missing_errors_header() -> Result<(), ()>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 7 previous errors From d8716f5a3fb32dfaa77e298129dae193b0b8c650 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Mon, 17 Feb 2020 02:38:48 +0100 Subject: [PATCH 096/243] Fix ICE. --- clippy_lints/src/doc.rs | 45 +++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 133a20b669a1..c1285ad36467 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -153,11 +153,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DocMarkdown { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item<'_>) { let headers = check_attrs(cx, &self.valid_idents, &item.attrs); match item.kind { - hir::ItemKind::Fn(ref sig, ..) => { + hir::ItemKind::Fn(ref sig, _, body_id) => { if !(is_entrypoint_fn(cx, cx.tcx.hir().local_def_id(item.hir_id)) || in_external_macro(cx.tcx.sess, item.span)) { - lint_for_missing_headers(cx, item.hir_id, item.span, sig, headers); + lint_for_missing_headers(cx, item.hir_id, item.span, sig, headers, Some(body_id)); } }, hir::ItemKind::Impl { @@ -180,7 +180,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DocMarkdown { let headers = check_attrs(cx, &self.valid_idents, &item.attrs); if let hir::TraitItemKind::Method(ref sig, ..) = item.kind { if !in_external_macro(cx.tcx.sess, item.span) { - lint_for_missing_headers(cx, item.hir_id, item.span, sig, headers); + lint_for_missing_headers(cx, item.hir_id, item.span, sig, headers, None); } } } @@ -190,8 +190,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DocMarkdown { if self.in_trait_impl || in_external_macro(cx.tcx.sess, item.span) { return; } - if let hir::ImplItemKind::Method(ref sig, ..) = item.kind { - lint_for_missing_headers(cx, item.hir_id, item.span, sig, headers); + if let hir::ImplItemKind::Method(ref sig, body_id) = item.kind { + lint_for_missing_headers(cx, item.hir_id, item.span, sig, headers, Some(body_id)); } } } @@ -202,6 +202,7 @@ fn lint_for_missing_headers<'a, 'tcx>( span: impl Into + Copy, sig: &hir::FnSig<'_>, headers: DocHeaders, + body_id: Option, ) { if !cx.access_levels.is_exported(hir_id) { return; // Private functions do not require doc comments @@ -222,24 +223,24 @@ fn lint_for_missing_headers<'a, 'tcx>( span, "docs for function returning `Result` missing `# Errors` section", ); - } else { - let def_id = cx.tcx.hir().local_def_id(hir_id); + } else if let (Some(body_id), Some(future)) = (body_id, get_trait_def_id(cx, &paths::FUTURE)) { + let def_id = cx.tcx.hir().body_owner_def_id(body_id); let mir = cx.tcx.optimized_mir(def_id); - if let Some(future) = get_trait_def_id(cx, &paths::FUTURE) { - if implements_trait(cx, mir.return_ty(), future, &[]) { - use TyKind::*; - - if let Opaque(_, subs) = mir.return_ty().kind { - if let Some(ty) = subs.types().next() { - if let Generator(_, subs, _) = ty.kind { - if match_type(cx, subs.as_generator().return_ty(def_id, cx.tcx), &paths::RESULT) { - span_lint( - cx, - MISSING_ERRORS_DOC, - span, - "docs for function returning `Result` missing `# Errors` section", - ); - } + let ret_ty = mir.return_ty(); + + if implements_trait(cx, ret_ty, future, &[]) { + use TyKind::*; + + if let Opaque(_, subs) = ret_ty.kind { + if let Some(ty) = subs.types().next() { + if let Generator(_, subs, _) = ty.kind { + if match_type(cx, subs.as_generator().return_ty(def_id, cx.tcx), &paths::RESULT) { + span_lint( + cx, + MISSING_ERRORS_DOC, + span, + "docs for function returning `Result` missing `# Errors` section", + ); } } } From 8e2dab3b3c37b50d4148a72e09e5713412570cf8 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Mon, 17 Feb 2020 12:18:00 +0100 Subject: [PATCH 097/243] Use `if_chain`. --- clippy_lints/src/doc.rs | 42 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index c1285ad36467..1bbb66189662 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -1,4 +1,5 @@ use crate::utils::{get_trait_def_id, implements_trait, is_entrypoint_fn, match_type, paths, return_ty, span_lint}; +use if_chain::if_chain; use itertools::Itertools; use rustc::lint::in_external_macro; use rustc::ty::TyKind; @@ -223,27 +224,26 @@ fn lint_for_missing_headers<'a, 'tcx>( span, "docs for function returning `Result` missing `# Errors` section", ); - } else if let (Some(body_id), Some(future)) = (body_id, get_trait_def_id(cx, &paths::FUTURE)) { - let def_id = cx.tcx.hir().body_owner_def_id(body_id); - let mir = cx.tcx.optimized_mir(def_id); - let ret_ty = mir.return_ty(); - - if implements_trait(cx, ret_ty, future, &[]) { - use TyKind::*; - - if let Opaque(_, subs) = ret_ty.kind { - if let Some(ty) = subs.types().next() { - if let Generator(_, subs, _) = ty.kind { - if match_type(cx, subs.as_generator().return_ty(def_id, cx.tcx), &paths::RESULT) { - span_lint( - cx, - MISSING_ERRORS_DOC, - span, - "docs for function returning `Result` missing `# Errors` section", - ); - } - } - } + } else { + use TyKind::*; + if_chain! { + if let Some(body_id) = body_id; + if let Some(future) = get_trait_def_id(cx, &paths::FUTURE); + let def_id = cx.tcx.hir().body_owner_def_id(body_id); + let mir = cx.tcx.optimized_mir(def_id); + let ret_ty = mir.return_ty(); + if implements_trait(cx, ret_ty, future, &[]); + if let Opaque(_, subs) = ret_ty.kind; + if let Some(ty) = subs.types().next(); + if let Generator(_, subs, _) = ty.kind; + if match_type(cx, subs.as_generator().return_ty(def_id, cx.tcx), &paths::RESULT); + then { + span_lint( + cx, + MISSING_ERRORS_DOC, + span, + "docs for function returning `Result` missing `# Errors` section", + ); } } } From ea5ac40a24dfac8e2b9834234d014872104e8444 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Mon, 17 Feb 2020 14:19:09 +0100 Subject: [PATCH 098/243] Remove use of `TyKind`. --- clippy_lints/src/doc.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 1bbb66189662..4a7d2a8b640e 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -2,7 +2,7 @@ use crate::utils::{get_trait_def_id, implements_trait, is_entrypoint_fn, match_t use if_chain::if_chain; use itertools::Itertools; use rustc::lint::in_external_macro; -use rustc::ty::TyKind; +use rustc::ty; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; @@ -225,7 +225,6 @@ fn lint_for_missing_headers<'a, 'tcx>( "docs for function returning `Result` missing `# Errors` section", ); } else { - use TyKind::*; if_chain! { if let Some(body_id) = body_id; if let Some(future) = get_trait_def_id(cx, &paths::FUTURE); @@ -233,9 +232,9 @@ fn lint_for_missing_headers<'a, 'tcx>( let mir = cx.tcx.optimized_mir(def_id); let ret_ty = mir.return_ty(); if implements_trait(cx, ret_ty, future, &[]); - if let Opaque(_, subs) = ret_ty.kind; - if let Some(ty) = subs.types().next(); - if let Generator(_, subs, _) = ty.kind; + if let ty::Opaque(_, subs) = ret_ty.kind; + if let Some(gen) = subs.types().next(); + if let ty::Generator(_, subs, _) = gen.kind; if match_type(cx, subs.as_generator().return_ty(def_id, cx.tcx), &paths::RESULT); then { span_lint( From e2fc801ad5a858109e1f4586692f9496881b7842 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Mon, 17 Feb 2020 13:47:42 -0500 Subject: [PATCH 099/243] needless_doctest_main: False positive for async fn Fixes #5188. --- clippy_lints/src/doc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 4a7d2a8b640e..2968daa54b41 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -424,7 +424,7 @@ fn check_doc<'a, Events: Iterator, Range, text: &str, span: Span) { if text.contains("fn main() {") && !LEAVE_MAIN_PATTERNS.iter().any(|p| text.contains(p)) { From 6835e2d8e0983bd84fbd3795be34eb49118cca42 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 12 Feb 2020 17:16:39 +0100 Subject: [PATCH 100/243] Nuke Travis+AppVeyor CI --- .github/deploy_key.enc | Bin 1680 -> 0 bytes .travis.yml | 154 ----------------------------------------- Cargo.toml | 4 +- README.md | 2 - appveyor.yml | 47 ------------- ci/base-tests.sh | 55 --------------- 6 files changed, 1 insertion(+), 261 deletions(-) delete mode 100644 .github/deploy_key.enc delete mode 100644 .travis.yml delete mode 100644 appveyor.yml delete mode 100755 ci/base-tests.sh diff --git a/.github/deploy_key.enc b/.github/deploy_key.enc deleted file mode 100644 index 48cb3f5a1276dfdacef1d54cecd1ded0911738a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1680 zcmV;B25vF7u9N_L=w*TIYn1;MzUesW5ej2=oot?d>%{ zy=pH1(l$5zhk3TM$4_n%!q&1t*9w&T&t=Or-GHPK7bN}_feZhHHdR&H%g~fu8 z*f}0Udo-cU!f_}8=ay!LF^mdI-0d?3(@?B;SSW!+ZL5c1PDks2hcD%mUhf*AEOX!_ zOU@QB+)7ilyfBZ@cukZ)uLi1?TTviJa`BQYlNl6Da9f2!Pf__3o}Qy4{g+q6JG{|X z+A#u1gC(!>8kL`2OyiC4;APXVtcaHcyi!y#2EUg}LC-1QuNf2M$VV_Qpc>Ayfw7C# zISG~sUT6PTwLQn+MX8?=|y&G%V&|B`{XdC$vN{4|BAg7kQMQGf;rb+Pm`@V z^b+_}7%S_}=u!yQ{Nf|AGIWo=L@GlBv_z@Z+0SxYr>ha8hBE1?2hZ zUKy{$<<@oNXK5pO9&73B(mCVj6wakA2nQn?yqa9+MU;Dxzg%SciEkCP9zKm=*>ds% zn*2Sa4Xd4N-sF8rai#Y0TX*W|J0jZiv1SiSR~c?_-YTNA{J&;RU23E_>b?*pTJy*7 z>PCKgIytqqVbithll=TrYGbq4%|TM)1w&y@zRzrz%31DkcGw8X$|ww4cS-pp0oNbN z?;|O#9hZ*?6N~+667GvUz4+`r(Wthq`*j5|J$Trypc_ZabAI<>%S!^^sXHDK{DJI1 zlTb(%P1I=Ol}!hRe7KTcreEM$M>2e#CTt4_hu(5k?iEDE`md3E@^BjY&f5(%Cxu(0 z(=jt`&cM9Tx2^zK-vOHed{#^*O>CBZ|0G#Qw6kF>xYN-)CJ7>+HUoS~ zS}JCM8U8<9+~9-jPUAT<`@anfUP*q7T@Kak`g)q#G?;0fRCz6R3uU!^+a&NzZU@ig z!jg?*@Q~Q|^9fB6L{znl`E+2BVZp90UUcdb(J&U~TjmLd)d{0jn!;B*el6~m3Oj?7 zsyeBGF=A;5d9NJMt1n{&+LBBHH)B-7(+PBjowmB09RR<;{~;1bC%e*r$DS|-z2;En z@aL4dJw8CVYaj-V*!^Xddy?8T#+va<*+eJFGKJ5)80i*w+0^727+sFl#;k zp75P8*|UXDP9s@lStLfJ>?pk{=C%zFCgBqq(BB8f&pyzGDLapcLTE$W>)Xm1c+=Ga zXWh0Z##ii8_0#-OOrb&6%CB-Z+`$$*AXOyUcSuzN&vPYOEbeWtwY6X_bUtNd5s&e! zR8I+m7eWFHJ>bgUka?fw1AD-xAbKYNVBOXwR^@-sTNf*2f-yl>LkwLrC+< ztT-MogUA9+gjY&w6#fDTb?NjUx9O2_g3;QOC_9z-C5)`}qGa*PConYj9K_^4)XjbW z{(BKxnQj9py|JC4q>z!`t>f_GPTFf^LK$c5x4^>`gLX+j(&LbA927@TPjlF-HRKWQY0!(*fj-a`OQ@%|218fm aw@mexo81x=`|RI})%;EfbOs3kDMvfxY($g* diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index fa02f5334017..000000000000 --- a/.travis.yml +++ /dev/null @@ -1,154 +0,0 @@ -dist: xenial -language: bash -git: - depth: 1 - quiet: true - -branches: - # Don't build these branches - except: - # Used by bors - - trying.tmp - - staging.tmp - -cache: - directories: - - $HOME/.cargo -before_cache: - - cargo install cargo-cache --debug - - find $HOME/.cargo/bin/ ! -type d -exec strip {} \; - - cargo cache --autoclean - -env: - global: - - RUST_BACKTRACE=1 - - secure: "OKulfkA5OGd/d1IhvBKzRkHQwMcWjzrzbimo7+5NhkUkWxndAzl+719TB3wWvIh1i2wXXrEXsyZkXM5FtRrHm55v1VKQ5ibjEvFg1w3NIg81iDyoLq186fLqywvxGkOAFPrsePPsBj5USd5xvhwwbrjO6L7/RK6Z8shBwOSc41s=" - -before_install: - - export CARGO_TARGET_DIR="$TRAVIS_BUILD_DIR/target" - - | - case "$TRAVIS_OS_NAME" in - linux ) HOST=x86_64-unknown-linux-gnu;; - osx ) HOST=x86_64-apple-darwin;; - windows ) HOST=x86_64-pc-windows-msvc;; - esac - - curl -sSL https://sh.rustup.rs | sh -s -- -y --default-host="$HOST" --default-toolchain=nightly --profile=minimal - - export PATH="$HOME/.cargo/bin:$PATH" -install: - - | - if [[ -z ${INTEGRATION} ]]; then - if ! rustup component add rustfmt; then - TARGET=$(rustc -Vv | awk '/host/{print $2}') - NIGHTLY=$(curl -s "https://rust-lang.github.io/rustup-components-history/${TARGET}/rustfmt") - curl -sSL "https://static.rust-lang.org/dist/${NIGHTLY}/rustfmt-nightly-${TARGET}.tar.xz" | \ - tar -xJf - --strip-components=3 -C ~/.cargo/bin - rm -rf ~/.cargo/bin/doc - fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then - . $HOME/.nvm/nvm.sh - nvm install stable - nvm use stable - npm install remark-cli remark-lint remark-lint-maximum-line-length remark-preset-lint-recommended - elif [[ "$TRAVIS_OS_NAME" == "windows" ]]; then - choco install windows-sdk-10.1 - fi - fi - -# disabling the integration tests in forks should be done with -# if: fork = false -# but this is currently buggy travis-ci/travis-ci#9118 -matrix: - fast_finish: true - include: - # Builds that are executed for every PR - - os: linux - # i686 toolchain could run on x86_64 system. - - os: linux - env: HOST_TOOLCHAIN=i686-unknown-linux-gnu - addons: - apt: - packages: - - gcc-multilib - - libssl-dev:i386 # openssl dev in Cargo.toml - if: branch IN (auto, try) - - os: windows - env: CARGO_INCREMENTAL=0 OS_WINDOWS=true - - # Builds that are only executed when a PR is r+ed or a try build is started - # We don't want to run these always because they go towards - # the build limit within the Travis rust-lang account. - # The jobs are approximately sorted by execution time - - os: osx - if: branch IN (auto, try) - - env: INTEGRATION=rust-lang/rls - if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - - env: INTEGRATION=rust-lang/cargo - if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - - env: INTEGRATION=rust-lang/chalk - if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - - env: INTEGRATION=Geal/nom - if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - - env: INTEGRATION=rust-lang/rustfmt - if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - - env: INTEGRATION=hyperium/hyper - if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - - env: INTEGRATION=rust-itertools/itertools - if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - # FIXME: rustc ICE on `serde_test_suite` - # - env: INTEGRATION=serde-rs/serde - # if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - - env: INTEGRATION=rust-lang/stdarch - if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - - env: INTEGRATION=rust-random/rand - if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - - env: INTEGRATION=rust-lang/futures-rs - if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - - env: INTEGRATION=Marwes/combine - if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - - env: INTEGRATION=rust-lang-nursery/failure - if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - - env: INTEGRATION=rust-lang/log - if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - - env: INTEGRATION=chronotope/chrono - if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - allow_failures: - - os: windows - env: CARGO_INCREMENTAL=0 OS_WINDOWS=true - -before_script: - - | - if [[ "$TRAVIS_BRANCH" == "auto" ]] || [[ "$TRAVIS_BRANCH" == "try" ]]; then - PR=$(echo "$TRAVIS_COMMIT_MESSAGE" | grep -o "#[0-9]*" | head -1 | sed 's/^#//g') - output=$(curl -H "Authorization: token $GITHUB_API_TOKEN" -s "https://api.github.com/repos/rust-lang/rust-clippy/pulls/$PR" | \ - python -c "import sys, json; print(json.load(sys.stdin)['body'])" | \ - grep "^changelog: " | \ - sed "s/changelog: //g") - if [[ -z "$output" ]]; then - echo "ERROR: PR body must contain 'changelog: ...'" - exit 1 - elif [[ "$output" = "none" ]]; then - echo "WARNING: changelog is 'none'" - fi - fi - - | - rm rust-toolchain - ./setup-toolchain.sh - - | - SYSROOT=$(rustc --print sysroot) - case "$TRAVIS_OS_NAME" in - windows ) export PATH="${SYSROOT}/bin:${PATH}" ;; - linux ) export LD_LIBRARY_PATH="${SYSROOT}/lib${LD_LIBRARY_PATH+:${LD_LIBRARY_PATH}}" ;; - osx ) - # See - sudo mkdir -p /usr/local/lib - sudo find "$SYSROOT/lib" -maxdepth 1 -name '*.dylib' -exec ln -s {} /usr/local/lib \; - ;; - esac - -script: - - | - if [[ -n ${INTEGRATION} ]]; then - cargo test --test integration --features integration && sleep 5 - else - ./ci/base-tests.sh && sleep 5 - fi diff --git a/Cargo.toml b/Cargo.toml index aefbcec15f51..c1a410cf5c82 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,9 +18,7 @@ build = "build.rs" edition = "2018" publish = false -[badges] -travis-ci = { repository = "rust-lang/rust-clippy" } -appveyor = { repository = "rust-lang/rust-clippy" } +# [badges] # FIXME(flip1995): Add GHA badge once rust-lang/crates.io#1838 is merged [[bin]] diff --git a/README.md b/README.md index 39cc9310f512..628133a8a668 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # Clippy -[![Build Status](https://travis-ci.com/rust-lang/rust-clippy.svg?branch=master)](https://travis-ci.com/rust-lang/rust-clippy) -[![Windows Build status](https://ci.appveyor.com/api/projects/status/id677xpw1dguo7iw?svg=true)](https://ci.appveyor.com/project/rust-lang-libs/rust-clippy) [![Clippy Test](https://github.com/rust-lang/rust-clippy/workflows/Clippy%20Test/badge.svg?branch=auto&event=push)](https://github.com/rust-lang/rust-clippy/actions?query=workflow%3A%22Clippy+Test%22+event%3Apush+branch%3Aauto) [![License: MIT OR Apache-2.0](https://img.shields.io/crates/l/clippy.svg)](#license) diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index bf6133e98a06..000000000000 --- a/appveyor.yml +++ /dev/null @@ -1,47 +0,0 @@ -environment: - global: - PROJECT_NAME: rust-clippy - RUST_BACKTRACE: 1 - matrix: - #- TARGET: i686-pc-windows-gnu - #- TARGET: i686-pc-windows-msvc - #- TARGET: x86_64-pc-windows-gnu - - TARGET: x86_64-pc-windows-msvc - -branches: - # Only build AppVeyor on r+ and try branch - only: - - auto - - try - -cache: - - '%USERPROFILE%\.cargo' -# before cache -after_test: - - cargo install cargo-cache --debug - - cargo cache --autoclean - -install: - - curl -sSf -o rustup-init.exe https://win.rustup.rs/ - - rustup-init.exe -y --default-host %TARGET% --default-toolchain nightly --profile=minimal - - set PATH=%USERPROFILE%\.cargo\bin;%PATH% - - rustup component add rustfmt --toolchain nightly & exit 0 # Format test handles missing rustfmt - - del rust-toolchain - - cargo install rustup-toolchain-install-master - - rustup-toolchain-install-master -f -n master -c rustc-dev - - rustup override set master - - rustc -V - - cargo -V - -# Build settings, not to be confused with "before_build" and "after_build". -build: false - -build_script: - - cargo build --features deny-warnings - -test_script: - - cargo test --features deny-warnings - -notifications: - - provider: Email - on_build_success: false diff --git a/ci/base-tests.sh b/ci/base-tests.sh deleted file mode 100755 index 125a566271d0..000000000000 --- a/ci/base-tests.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env bash -set -ex - -echo "Running clippy base tests" - -PATH=$PATH:./node_modules/.bin -if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then - remark -f ./*.md -f doc/*.md > /dev/null -fi -# build clippy in debug mode and run tests -cargo build --features deny-warnings -cargo test --features deny-warnings - -(cd clippy_lints && cargo test --features deny-warnings) -(cd rustc_tools_util && cargo test --features deny-warnings) -(cd clippy_dev && cargo test --features deny-warnings) - -# make sure clippy can be called via ./path/to/cargo-clippy -( - cd clippy_workspace_tests - ../target/debug/cargo-clippy -) - -# Perform various checks for lint registration -cargo dev update_lints --check -cargo dev --limit-stderr-length - -# Check running clippy-driver without cargo -( - # Check sysroot handling - sysroot=$(./target/debug/clippy-driver --print sysroot) - test "$sysroot" = "$(rustc --print sysroot)" - - if [[ -z "$OS_WINDOWS" ]]; then - desired_sysroot=/tmp - else - desired_sysroot=C:/tmp - fi - sysroot=$(./target/debug/clippy-driver --sysroot $desired_sysroot --print sysroot) - test "$sysroot" = $desired_sysroot - - sysroot=$(SYSROOT=$desired_sysroot ./target/debug/clippy-driver --print sysroot) - test "$sysroot" = $desired_sysroot - - # Make sure this isn't set - clippy-driver should cope without it - unset CARGO_MANIFEST_DIR - - # Run a lint and make sure it produces the expected output. It's also expected to exit with code 1 - # FIXME: How to match the clippy invocation in compile-test.rs? - ./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/cstring.rs 2> cstring.stderr && exit 1 - sed -e 's,tests/ui,$DIR,' -e '/= help/d' cstring.stderr > normalized.stderr - diff normalized.stderr tests/ui/cstring.stderr - - # TODO: CLIPPY_CONF_DIR / CARGO_MANIFEST_DIR -) From f4b80394d7b2fd24b3d3a1a3eeea2e22ddc8974b Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 18 Feb 2020 20:50:10 +0900 Subject: [PATCH 101/243] Use `Vec::with_capacity()` as possible --- clippy_lints/src/booleans.rs | 2 +- clippy_lints/src/matches.rs | 2 +- clippy_lints/src/shadow.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 60e62542a725..ee4ab7a9701d 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -359,7 +359,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { } simplified.push(simple_negated); } - let mut improvements = Vec::new(); + let mut improvements = Vec::with_capacity(simplified.len()); 'simplified: for suggestion in &simplified { let simplified_stats = terminal_stats(suggestion); let mut improvement = false; diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index d753b664045d..72131084311a 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -724,7 +724,7 @@ fn is_panic_block(block: &Block<'_>) -> bool { fn check_match_ref_pats(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) { if has_only_ref_pats(arms) { - let mut suggs = Vec::new(); + let mut suggs = Vec::with_capacity(arms.len() + 1); let (title, msg) = if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, ref inner) = ex.kind { let span = ex.span.source_callsite(); suggs.push((span, Sugg::hir_with_macro_callsite(cx, inner, "..").to_string())); diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 28e3acdf6bea..8e2ede04476e 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -101,7 +101,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Shadow { } fn check_fn<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Body<'_>) { - let mut bindings = Vec::new(); + let mut bindings = Vec::with_capacity(decl.inputs.len()); for arg in iter_input_pats(decl, body) { if let PatKind::Binding(.., ident, _) = arg.pat.kind { bindings.push((ident.name, ident.span)) From 06cb96ed72e09b9f850ee3e08e50df0c51e02250 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 18 Feb 2020 22:28:18 +0900 Subject: [PATCH 102/243] Clean up imports --- clippy_lints/src/booleans.rs | 3 +-- clippy_lints/src/consts.rs | 1 - clippy_lints/src/escape.rs | 5 ++--- clippy_lints/src/indexing_slicing.rs | 14 ++++++-------- clippy_lints/src/loops.rs | 1 - clippy_lints/src/ptr.rs | 1 - clippy_lints/src/ptr_offset_with_cast.rs | 10 +++++----- clippy_lints/src/temporary_assignment.rs | 3 +-- clippy_lints/src/utils/internal_lints.rs | 8 +++----- clippy_lints/src/utils/sugg.rs | 3 +-- 10 files changed, 19 insertions(+), 30 deletions(-) diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index ee4ab7a9701d..d37f77cf6cc3 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -5,7 +5,6 @@ use crate::utils::{ use if_chain::if_chain; use rustc::hir::map::Map; use rustc_errors::Applicability; -use rustc_hir::intravisit; use rustc_hir::intravisit::*; use rustc_hir::*; use rustc_lint::{LateContext, LateLintPass}; @@ -60,7 +59,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonminimalBool { fn check_fn( &mut self, cx: &LateContext<'a, 'tcx>, - _: intravisit::FnKind<'tcx>, + _: FnKind<'tcx>, _: &'tcx FnDecl<'_>, body: &'tcx Body<'_>, _: Span, diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 211625aafbf8..5a79848c1287 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -11,7 +11,6 @@ use rustc_hir::*; use rustc_lint::LateContext; use rustc_span::symbol::Symbol; use std::cmp::Ordering::{self, Equal}; -use std::cmp::PartialOrd; use std::convert::TryInto; use std::hash::{Hash, Hasher}; use syntax::ast::{FloatTy, LitKind}; diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index ec1d3a24f036..73bd7b3a143c 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -1,7 +1,6 @@ use rustc::ty::layout::LayoutOf; use rustc::ty::{self, Ty}; -use rustc_hir::intravisit as visit; -use rustc_hir::HirIdSet; +use rustc_hir::intravisit; use rustc_hir::{self, *}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; @@ -54,7 +53,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxedLocal { fn check_fn( &mut self, cx: &LateContext<'a, 'tcx>, - _: visit::FnKind<'tcx>, + _: intravisit::FnKind<'tcx>, _: &'tcx FnDecl<'_>, body: &'tcx Body<'_>, _: Span, diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 30bb09fd8081..ac9442e96078 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -1,9 +1,7 @@ //! lint on indexing and slicing operations use crate::consts::{constant, Constant}; -use crate::utils; -use crate::utils::higher; -use crate::utils::higher::Range; +use crate::utils::{higher, span_lint, span_lint_and_help}; use rustc::ty; use rustc_hir::*; use rustc_lint::{LateContext, LateLintPass}; @@ -100,7 +98,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { if let (Some(start), _) = const_range { if start > size { - utils::span_lint( + span_lint( cx, OUT_OF_BOUNDS_INDEXING, range.start.map_or(expr.span, |start| start.span), @@ -112,7 +110,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { if let (_, Some(end)) = const_range { if end > size { - utils::span_lint( + span_lint( cx, OUT_OF_BOUNDS_INDEXING, range.end.map_or(expr.span, |end| end.span), @@ -136,7 +134,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { (None, None) => return, // [..] is ok. }; - utils::span_lint_and_help(cx, INDEXING_SLICING, expr.span, "slicing may panic.", help_msg); + span_lint_and_help(cx, INDEXING_SLICING, expr.span, "slicing may panic.", help_msg); } else { // Catchall non-range index, i.e., [n] or [n << m] if let ty::Array(..) = ty.kind { @@ -147,7 +145,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { } } - utils::span_lint_and_help( + span_lint_and_help( cx, INDEXING_SLICING, expr.span, @@ -163,7 +161,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { /// the range. If the start or end is not constant, None is returned. fn to_const_range<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, - range: Range<'_>, + range: higher::Range<'_>, array_size: u128, ) -> (Option, Option) { let s = range.start.map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c)); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 3eee2728ce2c..393fbd2aaefc 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -18,7 +18,6 @@ use rustc::ty::{self, Ty}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id; use rustc_hir::intravisit::{walk_block, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; use rustc_hir::*; use rustc_infer::infer::TyCtxtInferExt; diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 33cfa5d75c62..d868253b85cd 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -8,7 +8,6 @@ use crate::utils::{ use if_chain::if_chain; use rustc::ty; use rustc_errors::Applicability; -use rustc_hir::QPath; use rustc_hir::*; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 93bd3b57ad7e..ffc59d43750e 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -1,4 +1,4 @@ -use crate::utils; +use crate::utils::{snippet_opt, span_lint, span_lint_and_sugg}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -59,7 +59,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PtrOffsetWithCast { let msg = format!("use of `{}` with a `usize` casted to an `isize`", method); if let Some(sugg) = build_suggestion(cx, method, receiver_expr, cast_lhs_expr) { - utils::span_lint_and_sugg( + span_lint_and_sugg( cx, PTR_OFFSET_WITH_CAST, expr.span, @@ -69,7 +69,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PtrOffsetWithCast { Applicability::MachineApplicable, ); } else { - utils::span_lint(cx, PTR_OFFSET_WITH_CAST, expr.span, &msg); + span_lint(cx, PTR_OFFSET_WITH_CAST, expr.span, &msg); } } } @@ -119,8 +119,8 @@ fn build_suggestion<'a, 'tcx>( receiver_expr: &Expr<'_>, cast_lhs_expr: &Expr<'_>, ) -> Option { - let receiver = utils::snippet_opt(cx, receiver_expr.span)?; - let cast_lhs = utils::snippet_opt(cx, cast_lhs_expr.span)?; + let receiver = snippet_opt(cx, receiver_expr.span)?; + let cast_lhs = snippet_opt(cx, cast_lhs_expr.span)?; Some(format!("{}.{}({})", receiver, method.suggestion(), cast_lhs)) } diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index fec9ad256336..bbb883aaf328 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -1,5 +1,4 @@ -use crate::utils::is_adjusted; -use crate::utils::span_lint; +use crate::utils::{is_adjusted, span_lint}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 945999de89fe..759feafc75b7 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -11,12 +11,10 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::*; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; -use rustc_session::declare_tool_lint; -use rustc_session::{declare_lint_pass, impl_lint_pass}; +use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::{Span, Spanned}; use rustc_span::symbol::SymbolStr; -use syntax::ast; -use syntax::ast::{Crate as AstCrate, ItemKind, LitKind, Name}; +use syntax::ast::{Crate as AstCrate, ItemKind, LitKind, Name, NodeId}; use syntax::visit::FnKind; declare_clippy_lint! { @@ -380,7 +378,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OuterExpnDataPass { declare_lint_pass!(ProduceIce => [PRODUCE_ICE]); impl EarlyLintPass for ProduceIce { - fn check_fn(&mut self, _: &EarlyContext<'_>, fn_kind: FnKind<'_>, _: Span, _: ast::NodeId) { + fn check_fn(&mut self, _: &EarlyContext<'_>, fn_kind: FnKind<'_>, _: Span, _: NodeId) { if is_trigger_fn(fn_kind) { panic!("Would you like some help with that?"); } diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 3e694f40d193..5c9e3ab80bb5 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -12,9 +12,8 @@ use rustc_span::{BytePos, Pos}; use std::borrow::Cow; use std::convert::TryInto; use std::fmt::Display; -use syntax::ast; -use syntax::token; use syntax::util::parser::AssocOp; +use syntax::{ast, token}; pub use crate::literal_representation::format_numeric_literal; From 533422fcce7f0887f37b69a30f96216cff79afa1 Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Tue, 18 Feb 2020 08:04:02 -0800 Subject: [PATCH 103/243] Add `LOG2_10` and `LOG10_2` to `approx_const` lint --- clippy_lints/src/approx_const.rs | 4 +++- tests/ui/approx_const.rs | 6 ++++++ tests/ui/approx_const.stderr | 20 ++++++++++++++++---- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 123a0a9d1894..51b6f2f0688f 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -37,7 +37,7 @@ declare_clippy_lint! { } // Tuples are of the form (constant, name, min_digits) -const KNOWN_CONSTS: [(f64, &str, usize); 16] = [ +const KNOWN_CONSTS: [(f64, &str, usize); 18] = [ (f64::E, "E", 4), (f64::FRAC_1_PI, "FRAC_1_PI", 4), (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2", 5), @@ -52,6 +52,8 @@ const KNOWN_CONSTS: [(f64, &str, usize); 16] = [ (f64::LN_2, "LN_2", 5), (f64::LOG10_E, "LOG10_E", 5), (f64::LOG2_E, "LOG2_E", 5), + (f64::LOG2_10, "LOG2_10", 5), + (f64::LOG10_2, "LOG10_2", 5), (f64::PI, "PI", 3), (f64::SQRT_2, "SQRT_2", 5), ]; diff --git a/tests/ui/approx_const.rs b/tests/ui/approx_const.rs index 8c295d1438a7..e1c150fdefd4 100644 --- a/tests/ui/approx_const.rs +++ b/tests/ui/approx_const.rs @@ -45,6 +45,12 @@ fn main() { let my_log2_e = 1.4426950408889634; let no_log2_e = 1.442; + let log2_10 = 3.321928094887362; + let no_log2_10 = 3.321; + + let log10_2 = 0.301029995663981; + let no_log10_2 = 0.301; + let my_pi = 3.1415; let almost_pi = 3.14; let no_pi = 3.15; diff --git a/tests/ui/approx_const.stderr b/tests/ui/approx_const.stderr index 71c1c360e74a..98b85443f0b7 100644 --- a/tests/ui/approx_const.stderr +++ b/tests/ui/approx_const.stderr @@ -96,23 +96,35 @@ error: approximate value of `f{32, 64}::consts::LOG2_E` found. Consider using it LL | let my_log2_e = 1.4426950408889634; | ^^^^^^^^^^^^^^^^^^ +error: approximate value of `f{32, 64}::consts::LOG2_10` found. Consider using it directly + --> $DIR/approx_const.rs:48:19 + | +LL | let log2_10 = 3.321928094887362; + | ^^^^^^^^^^^^^^^^^ + +error: approximate value of `f{32, 64}::consts::LOG10_2` found. Consider using it directly + --> $DIR/approx_const.rs:51:19 + | +LL | let log10_2 = 0.301029995663981; + | ^^^^^^^^^^^^^^^^^ + error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly - --> $DIR/approx_const.rs:48:17 + --> $DIR/approx_const.rs:54:17 | LL | let my_pi = 3.1415; | ^^^^^^ error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly - --> $DIR/approx_const.rs:49:21 + --> $DIR/approx_const.rs:55:21 | LL | let almost_pi = 3.14; | ^^^^ error: approximate value of `f{32, 64}::consts::SQRT_2` found. Consider using it directly - --> $DIR/approx_const.rs:52:18 + --> $DIR/approx_const.rs:58:18 | LL | let my_sq2 = 1.4142; | ^^^^^^ -error: aborting due to 19 previous errors +error: aborting due to 21 previous errors From aa4cf72f28b8cca50f27244502c1b32af4301011 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 19 Feb 2020 07:33:19 +0900 Subject: [PATCH 104/243] Rustup to rust-lang/rust#69181 --- clippy_lints/src/consts.rs | 7 ++++--- clippy_lints/src/enum_clike.rs | 8 ++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 5a79848c1287..7efc62d4c2e1 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -226,7 +226,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { return self.ifthenelse(cond, then, otherwise); } match e.kind { - ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id), + ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id, self.tables.expr_ty(e)), ExprKind::Block(ref block, _) => self.block(block), ExprKind::Lit(ref lit) => Some(lit_to_constant(&lit.node, self.tables.expr_ty_opt(e))), ExprKind::Array(ref vec) => self.multi(vec).map(Constant::Vec), @@ -319,7 +319,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } /// Lookup a possibly constant expression from a `ExprKind::Path`. - fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId) -> Option { + fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'cc>) -> Option { let res = self.tables.qpath_res(qpath, id); match res { Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => { @@ -334,7 +334,8 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { .lcx .tcx .const_eval_resolve(self.param_env, def_id, substs, None, None) - .ok()?; + .ok() + .map(|val| rustc::ty::Const::from_value(self.lcx.tcx, val, ty))?; let result = miri_to_const(&result); if result.is_some() { self.needed_resolution = true; diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 52ac1ff71250..2e14956ecd7b 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -46,9 +46,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { for var in def.variants { if let Some(anon_const) = &var.disr_expr { let def_id = cx.tcx.hir().body_owner_def_id(anon_const.body); - let constant = cx.tcx.const_eval_poly(def_id).ok(); + let mut ty = cx.tcx.type_of(def_id); + let constant = cx + .tcx + .const_eval_poly(def_id) + .ok() + .map(|val| rustc::ty::Const::from_value(cx.tcx, val, ty)); if let Some(Constant::Int(val)) = constant.and_then(miri_to_const) { - let mut ty = cx.tcx.type_of(def_id); if let ty::Adt(adt, _) = ty.kind { if adt.is_enum() { ty = adt.repr.discr_type().to_ty(cx.tcx); From 79c0cf0cc9b2afcf59e533e633dd9e61065307e5 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 19 Feb 2020 10:43:49 +0900 Subject: [PATCH 105/243] Rustup to rust-lang/rust#69194 --- clippy_lints/src/excessive_bools.rs | 2 +- clippy_lints/src/non_expressive_names.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/excessive_bools.rs b/clippy_lints/src/excessive_bools.rs index a1bfb0a71010..aa91ab3bc774 100644 --- a/clippy_lints/src/excessive_bools.rs +++ b/clippy_lints/src/excessive_bools.rs @@ -162,7 +162,7 @@ impl EarlyLintPass for ExcessiveBools { } | ItemKind::Trait(_, _, _, _, items) => { for item in items { - if let AssocItemKind::Fn(fn_sig, _) = &item.kind { + if let AssocItemKind::Fn(fn_sig, _, _) = &item.kind { self.check_fn_sig(cx, fn_sig, item.span); } } diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 2a7fbe6c0c64..5411e3246159 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -358,7 +358,7 @@ impl EarlyLintPass for NonExpressiveNames { } fn check_impl_item(&mut self, cx: &EarlyContext<'_>, item: &AssocItem) { - if let AssocItemKind::Fn(ref sig, Some(ref blk)) = item.kind { + if let AssocItemKind::Fn(ref sig, _, Some(ref blk)) = item.kind { do_check(self, cx, &item.attrs, &sig.decl, blk); } } From 1c5c054e4cb59fe05f574ae6322794f93569dd8b Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 14 Feb 2020 14:07:06 +0900 Subject: [PATCH 106/243] Rename for clarity --- clippy_lints/src/redundant_clone.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 66faecbef2ad..109bea7fff2a 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -452,7 +452,7 @@ impl<'a, 'tcx> PossibleBorrowerVisitor<'a, 'tcx> { self, cx: &LateContext<'a, 'tcx>, maybe_live: DataflowResults<'tcx, MaybeStorageLive<'a, 'tcx>>, - ) -> PossibleBorrower<'a, 'tcx> { + ) -> PossibleBorrowerMap<'a, 'tcx> { let mut map = FxHashMap::default(); for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) { if is_copy(cx, self.body.local_decls[row].ty) { @@ -475,7 +475,7 @@ impl<'a, 'tcx> PossibleBorrowerVisitor<'a, 'tcx> { } let bs = BitSet::new_empty(self.body.local_decls.len()); - PossibleBorrower { + PossibleBorrowerMap { map, maybe_live: DataflowResultsCursor::new(maybe_live, self.body), bitset: (bs.clone(), bs), @@ -557,7 +557,7 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) { } /// Result of `PossibleBorrowerVisitor`. -struct PossibleBorrower<'a, 'tcx> { +struct PossibleBorrowerMap<'a, 'tcx> { /// Mapping `Local -> its possible borrowers` map: FxHashMap>, maybe_live: DataflowResultsCursor<'a, 'tcx, MaybeStorageLive<'a, 'tcx>>, @@ -565,7 +565,7 @@ struct PossibleBorrower<'a, 'tcx> { bitset: (BitSet, BitSet), } -impl PossibleBorrower<'_, '_> { +impl PossibleBorrowerMap<'_, '_> { /// Returns true if the set of borrowers of `borrowed` living at `at` matches with `borrowers`. fn only_borrowers(&mut self, borrowers: &[mir::Local], borrowed: mir::Local, at: mir::Location) -> bool { self.maybe_live.seek(at); From 9d254545f386552e27033f9e395cfb21fcd0f569 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 14 Feb 2020 14:42:10 +0900 Subject: [PATCH 107/243] Migrate to generic dataflow --- clippy_lints/src/redundant_clone.rs | 81 +++++++++++++---------------- 1 file changed, 36 insertions(+), 45 deletions(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 109bea7fff2a..e419ae09a3f9 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -15,9 +15,8 @@ use rustc_hir::intravisit::FnKind; use rustc_hir::{def_id, Body, FnDecl, HirId}; use rustc_index::bit_set::{BitSet, HybridBitSet}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_mir::dataflow::{ - do_dataflow, BitDenotation, BottomValue, DataflowResults, DataflowResultsCursor, DebugFormatted, GenKillSet, -}; +use rustc_mir::dataflow::generic::{Analysis, AnalysisDomain, GenKill, GenKillAnalysis, ResultsCursor}; +use rustc_mir::dataflow::BottomValue; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::{BytePos, Span}; use std::convert::TryFrom; @@ -83,16 +82,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { let mir = cx.tcx.optimized_mir(def_id); let mir_read_only = mir.unwrap_read_only(); - let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len()); - let maybe_storage_live_result = do_dataflow( - cx.tcx, - mir, - def_id, - &[], - &dead_unwinds, - MaybeStorageLive::new(mir), - |bd, p| DebugFormatted::new(&bd.body.local_decls[p]), - ); + let maybe_storage_live_result = MaybeStorageLive + .into_engine(cx.tcx, mir, def_id) + .iterate_to_fixpoint() + .into_results_cursor(mir); let mut possible_borrower = { let mut vis = PossibleBorrowerVisitor::new(cx, mir); vis.visit_body(mir_read_only); @@ -377,34 +370,25 @@ impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor { /// Determines liveness of each local purely based on `StorageLive`/`Dead`. #[derive(Copy, Clone)] -struct MaybeStorageLive<'a, 'tcx> { - body: &'a mir::Body<'tcx>, -} - -impl<'a, 'tcx> MaybeStorageLive<'a, 'tcx> { - fn new(body: &'a mir::Body<'tcx>) -> Self { - MaybeStorageLive { body } - } -} +struct MaybeStorageLive; -impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> { +impl<'tcx> AnalysisDomain<'tcx> for MaybeStorageLive { type Idx = mir::Local; - fn name() -> &'static str { - "maybe_storage_live" - } - fn bits_per_block(&self) -> usize { - self.body.local_decls.len() + const NAME: &'static str = "maybe_storage_live"; + + fn bits_per_block(&self, body: &mir::Body<'tcx>) -> usize { + body.local_decls.len() } - fn start_block_effect(&self, on_entry: &mut BitSet) { - for arg in self.body.args_iter() { - on_entry.insert(arg); + fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut BitSet) { + for arg in body.args_iter() { + state.insert(arg); } } +} - fn statement_effect(&self, trans: &mut GenKillSet, loc: mir::Location) { - let stmt = &self.body[loc.block].statements[loc.statement_index]; - +impl<'tcx> GenKillAnalysis<'tcx> for MaybeStorageLive { + fn statement_effect(&self, trans: &mut impl GenKill, stmt: &mir::Statement<'tcx>, _: mir::Location) { match stmt.kind { mir::StatementKind::StorageLive(l) => trans.gen(l), mir::StatementKind::StorageDead(l) => trans.kill(l), @@ -412,20 +396,27 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> { } } - fn terminator_effect(&self, _trans: &mut GenKillSet, _loc: mir::Location) {} + fn terminator_effect( + &self, + _trans: &mut impl GenKill, + _terminator: &mir::Terminator<'tcx>, + _loc: mir::Location, + ) { + } - fn propagate_call_return( + fn call_return_effect( &self, - _in_out: &mut BitSet, - _call_bb: mir::BasicBlock, - _dest_bb: mir::BasicBlock, - _dest_place: &mir::Place<'tcx>, + _in_out: &mut impl GenKill, + _block: mir::BasicBlock, + _func: &mir::Operand<'tcx>, + _args: &[mir::Operand<'tcx>], + _return_place: &mir::Place<'tcx>, ) { // Nothing to do when a call returns successfully } } -impl<'a, 'tcx> BottomValue for MaybeStorageLive<'a, 'tcx> { +impl BottomValue for MaybeStorageLive { /// bottom = dead const BOTTOM_VALUE: bool = false; } @@ -451,7 +442,7 @@ impl<'a, 'tcx> PossibleBorrowerVisitor<'a, 'tcx> { fn into_map( self, cx: &LateContext<'a, 'tcx>, - maybe_live: DataflowResults<'tcx, MaybeStorageLive<'a, 'tcx>>, + maybe_live: ResultsCursor<'tcx, 'tcx, MaybeStorageLive>, ) -> PossibleBorrowerMap<'a, 'tcx> { let mut map = FxHashMap::default(); for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) { @@ -477,7 +468,7 @@ impl<'a, 'tcx> PossibleBorrowerVisitor<'a, 'tcx> { let bs = BitSet::new_empty(self.body.local_decls.len()); PossibleBorrowerMap { map, - maybe_live: DataflowResultsCursor::new(maybe_live, self.body), + maybe_live, bitset: (bs.clone(), bs), } } @@ -560,7 +551,7 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) { struct PossibleBorrowerMap<'a, 'tcx> { /// Mapping `Local -> its possible borrowers` map: FxHashMap>, - maybe_live: DataflowResultsCursor<'a, 'tcx, MaybeStorageLive<'a, 'tcx>>, + maybe_live: ResultsCursor<'a, 'tcx, MaybeStorageLive>, // Caches to avoid allocation of `BitSet` on every query bitset: (BitSet, BitSet), } @@ -568,7 +559,7 @@ struct PossibleBorrowerMap<'a, 'tcx> { impl PossibleBorrowerMap<'_, '_> { /// Returns true if the set of borrowers of `borrowed` living at `at` matches with `borrowers`. fn only_borrowers(&mut self, borrowers: &[mir::Local], borrowed: mir::Local, at: mir::Location) -> bool { - self.maybe_live.seek(at); + self.maybe_live.seek_after(at); self.bitset.0.clear(); let maybe_live = &mut self.maybe_live; From 2323343a589a1a6c409571dc7849e396fac7fb68 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 20 Feb 2020 12:05:12 +0100 Subject: [PATCH 108/243] Add Copyright claim, where missing --- LICENSE-APACHE | 2 +- LICENSE-MIT | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/LICENSE-APACHE b/LICENSE-APACHE index 16fe87b06e80..d821a4de2bed 100644 --- a/LICENSE-APACHE +++ b/LICENSE-APACHE @@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work. same "printed page" as the copyright notice for easier identification within third-party archives. -Copyright [yyyy] [name of copyright owner] +Copyright 2014-2020 The Rust Project Developers Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/LICENSE-MIT b/LICENSE-MIT index 31aa79387f27..b7c70dd4026d 100644 --- a/LICENSE-MIT +++ b/LICENSE-MIT @@ -1,3 +1,7 @@ +MIT License + +Copyright (c) 2014-2020 The Rust Project Developers + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the From 7a85b7761b6a624458c8476c2ecc85fa63d051d0 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 20 Feb 2020 12:05:34 +0100 Subject: [PATCH 109/243] Update Copyright year --- README.md | 2 +- rustc_tools_util/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 628133a8a668..444d79bcb277 100644 --- a/README.md +++ b/README.md @@ -182,7 +182,7 @@ If you want to contribute to Clippy, you can find more information in [CONTRIBUT ## License -Copyright 2014-2019 The Rust Project Developers +Copyright 2014-2020 The Rust Project Developers Licensed under the Apache License, Version 2.0 or the MIT license diff --git a/rustc_tools_util/README.md b/rustc_tools_util/README.md index 18341ca2f280..6027538dc4ab 100644 --- a/rustc_tools_util/README.md +++ b/rustc_tools_util/README.md @@ -53,7 +53,7 @@ This gives the following output in clippy: ## License -Copyright 2014-2019 The Rust Project Developers +Copyright 2014-2020 The Rust Project Developers Licensed under the Apache License, Version 2.0 or the MIT license From fb989d3215ca982ce4e719faf0f370e131f9f42f Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 20 Feb 2020 12:06:06 +0100 Subject: [PATCH 110/243] Remove remaining license header in test file --- tests/ui/mem_replace.fixed | 9 --------- tests/ui/mem_replace.rs | 9 --------- tests/ui/mem_replace.stderr | 10 +++++----- 3 files changed, 5 insertions(+), 23 deletions(-) diff --git a/tests/ui/mem_replace.fixed b/tests/ui/mem_replace.fixed index 58657b934fbf..54e962e7116e 100644 --- a/tests/ui/mem_replace.fixed +++ b/tests/ui/mem_replace.fixed @@ -1,12 +1,3 @@ -// 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. - // run-rustfix #![allow(unused_imports)] #![warn( diff --git a/tests/ui/mem_replace.rs b/tests/ui/mem_replace.rs index eac0ce586a08..60f527810716 100644 --- a/tests/ui/mem_replace.rs +++ b/tests/ui/mem_replace.rs @@ -1,12 +1,3 @@ -// 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. - // run-rustfix #![allow(unused_imports)] #![warn( diff --git a/tests/ui/mem_replace.stderr b/tests/ui/mem_replace.stderr index d5dc66873b2f..245d33aa4f26 100644 --- a/tests/ui/mem_replace.stderr +++ b/tests/ui/mem_replace.stderr @@ -1,5 +1,5 @@ error: replacing an `Option` with `None` - --> $DIR/mem_replace.rs:23:13 + --> $DIR/mem_replace.rs:14:13 | LL | let _ = mem::replace(&mut an_option, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` @@ -7,13 +7,13 @@ LL | let _ = mem::replace(&mut an_option, None); = note: `-D clippy::mem-replace-option-with-none` implied by `-D warnings` error: replacing an `Option` with `None` - --> $DIR/mem_replace.rs:25:13 + --> $DIR/mem_replace.rs:16:13 | LL | let _ = mem::replace(an_option, None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:30:13 + --> $DIR/mem_replace.rs:21:13 | LL | let _ = std::mem::replace(&mut s, String::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut s)` @@ -21,13 +21,13 @@ LL | let _ = std::mem::replace(&mut s, String::default()); = note: `-D clippy::mem-replace-with-default` implied by `-D warnings` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:32:13 + --> $DIR/mem_replace.rs:23:13 | LL | let _ = std::mem::replace(s, String::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(s)` error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` - --> $DIR/mem_replace.rs:33:13 + --> $DIR/mem_replace.rs:24:13 | LL | let _ = std::mem::replace(s, Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(s)` From 78a250773631002303a24455eef7a8e7e7fbe619 Mon Sep 17 00:00:00 2001 From: Nipunn Koorapati Date: Wed, 19 Feb 2020 15:32:59 -0800 Subject: [PATCH 111/243] Move unneeded_field_pattern to restriction group Fixes https://github.com/rust-lang/rust-clippy/issues/1741 --- clippy_lints/src/lib.rs | 3 +-- clippy_lints/src/misc_early.rs | 2 +- src/lintlist/mod.rs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 8bd0d187061a..409e2863f9af 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1033,6 +1033,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::RESULT_UNWRAP_USED), LintId::of(&methods::WRONG_PUB_SELF_CONVENTION), LintId::of(&misc::FLOAT_CMP_CONST), + LintId::of(&misc_early::UNNEEDED_FIELD_PATTERN), LintId::of(&missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS), LintId::of(&missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS), LintId::of(&modulo_arithmetic::MODULO_ARITHMETIC), @@ -1270,7 +1271,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&misc_early::MIXED_CASE_HEX_LITERALS), LintId::of(&misc_early::REDUNDANT_CLOSURE_CALL), LintId::of(&misc_early::REDUNDANT_PATTERN), - LintId::of(&misc_early::UNNEEDED_FIELD_PATTERN), LintId::of(&misc_early::UNNEEDED_WILDCARD_PATTERN), LintId::of(&misc_early::ZERO_PREFIXED_LITERAL), LintId::of(&mut_key::MUTABLE_KEY_TYPE), @@ -1433,7 +1433,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&misc_early::DUPLICATE_UNDERSCORE_ARGUMENT), LintId::of(&misc_early::MIXED_CASE_HEX_LITERALS), LintId::of(&misc_early::REDUNDANT_PATTERN), - LintId::of(&misc_early::UNNEEDED_FIELD_PATTERN), LintId::of(&mut_reference::UNNECESSARY_MUT_PASSED), LintId::of(&neg_multiply::NEG_MULTIPLY), LintId::of(&new_without_default::NEW_WITHOUT_DEFAULT), diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index b28a61eb6219..3f17ac3de228 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -25,7 +25,7 @@ declare_clippy_lint! { /// let { a: _, b: ref b, c: _ } = .. /// ``` pub UNNEEDED_FIELD_PATTERN, - style, + restriction, "struct fields bound to a wildcard instead of using `..`" } diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 8c04afce1d27..6ed67681cb12 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2228,7 +2228,7 @@ pub const ALL_LINTS: [Lint; 355] = [ }, Lint { name: "unneeded_field_pattern", - group: "style", + group: "restriction", desc: "struct fields bound to a wildcard instead of using `..`", deprecation: None, module: "misc_early", From 4f85bc2fe9299778223b6d72573ce613d47d739d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 20 Feb 2020 23:54:10 +0100 Subject: [PATCH 112/243] rustup https://github.com/rust-lang/rust/pull/69325, update test stderr --- tests/ui/indexing_slicing_index.stderr | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/ui/indexing_slicing_index.stderr b/tests/ui/indexing_slicing_index.stderr index b4fac2a0fe05..ac5f0d0a39e8 100644 --- a/tests/ui/indexing_slicing_index.stderr +++ b/tests/ui/indexing_slicing_index.stderr @@ -1,22 +1,22 @@ -error: index out of bounds: the len is 4 but the index is 4 +error: this operation will panic at runtime --> $DIR/indexing_slicing_index.rs:11:5 | LL | x[4]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. - | ^^^^ + | ^^^^ index out of bounds: the len is 4 but the index is 4 | - = note: `#[deny(const_err)]` on by default + = note: `#[deny(unconditional_panic)]` on by default -error: index out of bounds: the len is 4 but the index is 8 +error: this operation will panic at runtime --> $DIR/indexing_slicing_index.rs:12:5 | LL | x[1 << 3]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. - | ^^^^^^^^^ + | ^^^^^^^^^ index out of bounds: the len is 4 but the index is 8 -error: index out of bounds: the len is 4 but the index is 15 +error: this operation will panic at runtime --> $DIR/indexing_slicing_index.rs:27:5 | LL | x[N]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. - | ^^^^ + | ^^^^ index out of bounds: the len is 4 but the index is 15 error: indexing may panic. --> $DIR/indexing_slicing_index.rs:10:5 From ce896ae96da14ed2b7557ece554033b051fdd7b5 Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Thu, 20 Feb 2020 21:20:49 -0800 Subject: [PATCH 113/243] Rustup to rust-lang/rust#69072 --- clippy_lints/src/len_zero.rs | 14 ++++++++------ clippy_lints/src/use_self.rs | 8 +------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index b1ed88f59d4a..aa538a4be9de 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -147,7 +147,7 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item<'_>, trait_i let is_empty_method_found = current_and_super_traits .iter() - .flat_map(|&i| cx.tcx.associated_items(i)) + .flat_map(|&i| cx.tcx.associated_items(i).in_definition_order()) .any(|i| { i.kind == ty::AssocKind::Method && i.method_has_self_argument @@ -276,10 +276,12 @@ fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { /// Checks the inherent impl's items for an `is_empty(self)` method. fn has_is_empty_impl(cx: &LateContext<'_, '_>, id: DefId) -> bool { - cx.tcx - .inherent_impls(id) - .iter() - .any(|imp| cx.tcx.associated_items(*imp).iter().any(|item| is_is_empty(cx, &item))) + cx.tcx.inherent_impls(id).iter().any(|imp| { + cx.tcx + .associated_items(*imp) + .in_definition_order() + .any(|item| is_is_empty(cx, &item)) + }) } let ty = &walk_ptrs_ty(cx.tables.expr_ty(expr)); @@ -288,7 +290,7 @@ fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { if let Some(principal) = tt.principal() { cx.tcx .associated_items(principal.def_id()) - .iter() + .in_definition_order() .any(|item| is_is_empty(cx, &item)) } else { false diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index da961a5f89da..f1d66c1bc25c 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -125,13 +125,7 @@ fn check_trait_method_impl_decl<'a, 'tcx>( let trait_method = cx .tcx .associated_items(impl_trait_ref.def_id) - .iter() - .find(|assoc_item| { - assoc_item.kind == ty::AssocKind::Method - && cx - .tcx - .hygienic_eq(impl_item.ident, assoc_item.ident, impl_trait_ref.def_id) - }) + .find_by_name_and_kind(cx.tcx, impl_item.ident, ty::AssocKind::Method, impl_trait_ref.def_id) .expect("impl method matches a trait method"); let trait_method_sig = cx.tcx.fn_sig(trait_method.def_id); From 219c94d02848c87db16c99ac2c6b30728713f58e Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Thu, 20 Feb 2020 18:32:06 -0800 Subject: [PATCH 114/243] Separate out lint to check lossy whole number float literals --- CHANGELOG.md | 1 + README.md | 2 +- ...xcessive_precision.rs => float_literal.rs} | 79 +++++++++++++------ clippy_lints/src/lib.rs | 12 +-- src/lintlist/mod.rs | 13 ++- tests/ui/excessive_precision.fixed | 22 ------ tests/ui/excessive_precision.rs | 22 ------ tests/ui/excessive_precision.stderr | 68 +--------------- tests/ui/lossy_float_literal.fixed | 35 ++++++++ tests/ui/lossy_float_literal.rs | 35 ++++++++ tests/ui/lossy_float_literal.stderr | 70 ++++++++++++++++ 11 files changed, 214 insertions(+), 145 deletions(-) rename clippy_lints/src/{excessive_precision.rs => float_literal.rs} (68%) create mode 100644 tests/ui/lossy_float_literal.fixed create mode 100644 tests/ui/lossy_float_literal.rs create mode 100644 tests/ui/lossy_float_literal.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f527a407db7..05ebe97d7b01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1207,6 +1207,7 @@ Released 2018-09-13 [`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value [`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist [`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug +[`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal [`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion [`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy [`manual_mul_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_mul_add diff --git a/README.md b/README.md index 444d79bcb277..f2ffea7d23cf 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 355 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 356 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/float_literal.rs similarity index 68% rename from clippy_lints/src/excessive_precision.rs rename to clippy_lints/src/float_literal.rs index 781d85a00e4f..8707259a2c88 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/float_literal.rs @@ -13,8 +13,7 @@ declare_clippy_lint! { /// **What it does:** Checks for float literals with a precision greater /// than that supported by the underlying type. /// - /// **Why is this bad?** Rust will silently lose precision during conversion - /// to a float. + /// **Why is this bad?** Rust will truncate the literal silently. /// /// **Known problems:** None. /// @@ -22,21 +21,45 @@ declare_clippy_lint! { /// /// ```rust /// // Bad - /// let a: f32 = 0.123_456_789_9; // 0.123_456_789 - /// let b: f32 = 16_777_217.0; // 16_777_216.0 + /// let v: f32 = 0.123_456_789_9; + /// println!("{}", v); // 0.123_456_789 /// /// // Good - /// let a: f64 = 0.123_456_789_9; - /// let b: f64 = 16_777_216.0; + /// let v: f64 = 0.123_456_789_9; + /// println!("{}", v); // 0.123_456_789_9 /// ``` pub EXCESSIVE_PRECISION, - correctness, + style, "excessive precision for float literal" } -declare_lint_pass!(ExcessivePrecision => [EXCESSIVE_PRECISION]); +declare_clippy_lint! { + /// **What it does:** Checks for whole number float literals that + /// cannot be represented as the underlying type without loss. + /// + /// **Why is this bad?** Rust will silently lose precision during + /// conversion to a float. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// // Bad + /// let _: f32 = 16_777_217.0; // 16_777_216.0 + /// + /// // Good + /// let _: f32 = 16_777_216.0; + /// let _: f64 = 16_777_217.0; + /// ``` + pub LOSSY_FLOAT_LITERAL, + restriction, + "lossy whole number float literals" +} + +declare_lint_pass!(FloatLiteral => [EXCESSIVE_PRECISION, LOSSY_FLOAT_LITERAL]); -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatLiteral { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) { if_chain! { let ty = cx.tables.expr_ty(expr); @@ -52,26 +75,41 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision { // since we'll need the truncated string anyway. let digits = count_digits(&sym_str); let max = max_digits(fty); - let float_str = match fty { - FloatTy::F32 => sym_str.parse::().map(|f| formatter.format(f)), - FloatTy::F64 => sym_str.parse::().map(|f| formatter.format(f)), - }.unwrap(); let type_suffix = match lit_float_ty { LitFloatType::Suffixed(FloatTy::F32) => Some("f32"), LitFloatType::Suffixed(FloatTy::F64) => Some("f64"), _ => None }; + let (is_whole, mut float_str) = match fty { + FloatTy::F32 => { + let value = sym_str.parse::().unwrap(); + + (value.fract() == 0.0, formatter.format(value)) + }, + FloatTy::F64 => { + let value = sym_str.parse::().unwrap(); + + (value.fract() == 0.0, formatter.format(value)) + }, + }; - if is_whole_number(&sym_str, fty) { + if is_whole && !sym_str.contains(|c| c == 'e' || c == 'E') { // Normalize the literal by stripping the fractional portion if sym_str.split('.').next().unwrap() != float_str { + // If the type suffix is missing the suggestion would be + // incorrectly interpreted as an integer so adding a `.0` + // suffix to prevent that. + if type_suffix.is_none() { + float_str.push_str(".0"); + } + span_lint_and_sugg( cx, - EXCESSIVE_PRECISION, + LOSSY_FLOAT_LITERAL, expr.span, "literal cannot be represented as the underlying type without loss of precision", "consider changing the type or replacing it with", - format_numeric_literal(format!("{}.0", float_str).as_str(), type_suffix, true), + format_numeric_literal(&float_str, type_suffix, true), Applicability::MachineApplicable, ); } @@ -91,15 +129,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision { } } -// Checks whether a float literal is a whole number -#[must_use] -fn is_whole_number(sym_str: &str, fty: FloatTy) -> bool { - match fty { - FloatTy::F32 => sym_str.parse::().unwrap().fract() == 0.0, - FloatTy::F64 => sym_str.parse::().unwrap().fract() == 0.0, - } -} - #[must_use] fn max_digits(fty: FloatTy) -> u32 { match fty { diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 8bd0d187061a..8584d06b0cc0 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -205,10 +205,10 @@ pub mod escape; pub mod eta_reduction; pub mod eval_order_dependence; pub mod excessive_bools; -pub mod excessive_precision; pub mod exit; pub mod explicit_write; pub mod fallible_impl_from; +pub mod float_literal; pub mod format; pub mod formatting; pub mod functions; @@ -534,10 +534,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &eval_order_dependence::EVAL_ORDER_DEPENDENCE, &excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS, &excessive_bools::STRUCT_EXCESSIVE_BOOLS, - &excessive_precision::EXCESSIVE_PRECISION, &exit::EXIT, &explicit_write::EXPLICIT_WRITE, &fallible_impl_from::FALLIBLE_IMPL_FROM, + &float_literal::EXCESSIVE_PRECISION, + &float_literal::LOSSY_FLOAT_LITERAL, &format::USELESS_FORMAT, &formatting::POSSIBLE_MISSING_COMMA, &formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, @@ -836,7 +837,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box eq_op::EqOp); store.register_late_pass(|| box enum_glob_use::EnumGlobUse); store.register_late_pass(|| box enum_clike::UnportableVariant); - store.register_late_pass(|| box excessive_precision::ExcessivePrecision); + store.register_late_pass(|| box float_literal::FloatLiteral); let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold; store.register_late_pass(move || box bit_mask::BitMask::new(verbose_bit_mask_threshold)); store.register_late_pass(|| box ptr::Ptr); @@ -1016,6 +1017,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&dbg_macro::DBG_MACRO), LintId::of(&else_if_without_else::ELSE_IF_WITHOUT_ELSE), LintId::of(&exit::EXIT), + LintId::of(&float_literal::LOSSY_FLOAT_LITERAL), LintId::of(&implicit_return::IMPLICIT_RETURN), LintId::of(&indexing_slicing::INDEXING_SLICING), LintId::of(&inherent_impl::MULTIPLE_INHERENT_IMPL), @@ -1159,8 +1161,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&eta_reduction::REDUNDANT_CLOSURE), LintId::of(&eval_order_dependence::DIVERGING_SUB_EXPRESSION), LintId::of(&eval_order_dependence::EVAL_ORDER_DEPENDENCE), - LintId::of(&excessive_precision::EXCESSIVE_PRECISION), LintId::of(&explicit_write::EXPLICIT_WRITE), + LintId::of(&float_literal::EXCESSIVE_PRECISION), LintId::of(&format::USELESS_FORMAT), LintId::of(&formatting::POSSIBLE_MISSING_COMMA), LintId::of(&formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING), @@ -1386,6 +1388,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&enum_variants::MODULE_INCEPTION), LintId::of(&eq_op::OP_REF), LintId::of(&eta_reduction::REDUNDANT_CLOSURE), + LintId::of(&float_literal::EXCESSIVE_PRECISION), LintId::of(&formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING), LintId::of(&formatting::SUSPICIOUS_ELSE_FORMATTING), LintId::of(&formatting::SUSPICIOUS_UNARY_OP_FORMATTING), @@ -1566,7 +1569,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT), LintId::of(&eq_op::EQ_OP), LintId::of(&erasing_op::ERASING_OP), - LintId::of(&excessive_precision::EXCESSIVE_PRECISION), LintId::of(&formatting::POSSIBLE_MISSING_COMMA), LintId::of(&functions::NOT_UNSAFE_PTR_ARG_DEREF), LintId::of(&indexing_slicing::OUT_OF_BOUNDS_INDEXING), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 8c04afce1d27..51208d74655d 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -6,7 +6,7 @@ pub use lint::Lint; pub use lint::LINT_LEVELS; // begin lint list, do not remove this comment, it’s used in `update_lints` -pub const ALL_LINTS: [Lint; 355] = [ +pub const ALL_LINTS: [Lint; 356] = [ Lint { name: "absurd_extreme_comparisons", group: "correctness", @@ -492,10 +492,10 @@ pub const ALL_LINTS: [Lint; 355] = [ }, Lint { name: "excessive_precision", - group: "correctness", + group: "style", desc: "excessive precision for float literal", deprecation: None, - module: "excessive_precision", + module: "float_literal", }, Lint { name: "exit", @@ -1001,6 +1001,13 @@ pub const ALL_LINTS: [Lint; 355] = [ deprecation: None, module: "booleans", }, + Lint { + name: "lossy_float_literal", + group: "restriction", + desc: "lossy whole number float literals", + deprecation: None, + module: "float_literal", + }, Lint { name: "main_recursion", group: "style", diff --git a/tests/ui/excessive_precision.fixed b/tests/ui/excessive_precision.fixed index f32307ce9107..bf0325fec792 100644 --- a/tests/ui/excessive_precision.fixed +++ b/tests/ui/excessive_precision.fixed @@ -60,26 +60,4 @@ fn main() { // issue #2840 let num = 0.000_000_000_01e-10f64; - - // Lossy whole-number float literals - let _: f32 = 16_777_216.0; - let _: f32 = 16_777_220.0; - let _: f32 = 16_777_220.0; - let _: f32 = 16_777_220.0; - let _ = 16_777_220.0_f32; - let _: f32 = -16_777_220.0; - let _: f64 = 9_007_199_254_740_992.0; - let _: f64 = 9_007_199_254_740_992.0; - let _: f64 = 9_007_199_254_740_992.0; - let _ = 9_007_199_254_740_992.0_f64; - let _: f64 = -9_007_199_254_740_992.0; - - // Lossless whole number float literals - let _: f32 = 16_777_216.0; - let _: f32 = 16_777_218.0; - let _: f32 = 16_777_220.0; - let _: f32 = -16_777_216.0; - let _: f32 = -16_777_220.0; - let _: f64 = 9_007_199_254_740_992.0; - let _: f64 = -9_007_199_254_740_992.0; } diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index a3d317400278..ce4722a90f90 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -60,26 +60,4 @@ fn main() { // issue #2840 let num = 0.000_000_000_01e-10f64; - - // Lossy whole-number float literals - let _: f32 = 16_777_217.0; - let _: f32 = 16_777_219.0; - let _: f32 = 16_777_219.; - let _: f32 = 16_777_219.000; - let _ = 16_777_219f32; - let _: f32 = -16_777_219.0; - let _: f64 = 9_007_199_254_740_993.0; - let _: f64 = 9_007_199_254_740_993.; - let _: f64 = 9_007_199_254_740_993.000; - let _ = 9_007_199_254_740_993f64; - let _: f64 = -9_007_199_254_740_993.0; - - // Lossless whole number float literals - let _: f32 = 16_777_216.0; - let _: f32 = 16_777_218.0; - let _: f32 = 16_777_220.0; - let _: f32 = -16_777_216.0; - let _: f32 = -16_777_220.0; - let _: f64 = 9_007_199_254_740_992.0; - let _: f64 = -9_007_199_254_740_992.0; } diff --git a/tests/ui/excessive_precision.stderr b/tests/ui/excessive_precision.stderr index 8941bcfd86d8..599773f2f70c 100644 --- a/tests/ui/excessive_precision.stderr +++ b/tests/ui/excessive_precision.stderr @@ -108,71 +108,5 @@ error: float has excessive precision LL | let bad_bige32: f32 = 1.123_456_788_888E-10; | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8E-10` -error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/excessive_precision.rs:65:18 - | -LL | let _: f32 = 16_777_217.0; - | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_216.0` - -error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/excessive_precision.rs:66:18 - | -LL | let _: f32 = 16_777_219.0; - | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` - -error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/excessive_precision.rs:67:18 - | -LL | let _: f32 = 16_777_219.; - | ^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` - -error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/excessive_precision.rs:68:18 - | -LL | let _: f32 = 16_777_219.000; - | ^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` - -error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/excessive_precision.rs:69:13 - | -LL | let _ = 16_777_219f32; - | ^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0_f32` - -error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/excessive_precision.rs:70:19 - | -LL | let _: f32 = -16_777_219.0; - | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` - -error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/excessive_precision.rs:71:18 - | -LL | let _: f64 = 9_007_199_254_740_993.0; - | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` - -error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/excessive_precision.rs:72:18 - | -LL | let _: f64 = 9_007_199_254_740_993.; - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` - -error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/excessive_precision.rs:73:18 - | -LL | let _: f64 = 9_007_199_254_740_993.000; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` - -error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/excessive_precision.rs:74:13 - | -LL | let _ = 9_007_199_254_740_993f64; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0_f64` - -error: literal cannot be represented as the underlying type without loss of precision - --> $DIR/excessive_precision.rs:75:19 - | -LL | let _: f64 = -9_007_199_254_740_993.0; - | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` - -error: aborting due to 29 previous errors +error: aborting due to 18 previous errors diff --git a/tests/ui/lossy_float_literal.fixed b/tests/ui/lossy_float_literal.fixed new file mode 100644 index 000000000000..24e372354fc0 --- /dev/null +++ b/tests/ui/lossy_float_literal.fixed @@ -0,0 +1,35 @@ +// run-rustfix +#![warn(clippy::lossy_float_literal)] + +fn main() { + // Lossy whole-number float literals + let _: f32 = 16_777_216.0; + let _: f32 = 16_777_220.0; + let _: f32 = 16_777_220.0; + let _: f32 = 16_777_220.0; + let _ = 16_777_220_f32; + let _: f32 = -16_777_220.0; + let _: f64 = 9_007_199_254_740_992.0; + let _: f64 = 9_007_199_254_740_992.0; + let _: f64 = 9_007_199_254_740_992.0; + let _ = 9_007_199_254_740_992_f64; + let _: f64 = -9_007_199_254_740_992.0; + + // Lossless whole number float literals + let _: f32 = 16_777_216.0; + let _: f32 = 16_777_218.0; + let _: f32 = 16_777_220.0; + let _: f32 = -16_777_216.0; + let _: f32 = -16_777_220.0; + let _: f64 = 16_777_217.0; + let _: f64 = -16_777_217.0; + let _: f64 = 9_007_199_254_740_992.0; + let _: f64 = -9_007_199_254_740_992.0; + + // Ignored whole number float literals + let _: f32 = 1e25; + let _: f32 = 1E25; + let _: f64 = 1e99; + let _: f64 = 1E99; + let _: f32 = 0.1; +} diff --git a/tests/ui/lossy_float_literal.rs b/tests/ui/lossy_float_literal.rs new file mode 100644 index 000000000000..3dcf98fa0bdd --- /dev/null +++ b/tests/ui/lossy_float_literal.rs @@ -0,0 +1,35 @@ +// run-rustfix +#![warn(clippy::lossy_float_literal)] + +fn main() { + // Lossy whole-number float literals + let _: f32 = 16_777_217.0; + let _: f32 = 16_777_219.0; + let _: f32 = 16_777_219.; + let _: f32 = 16_777_219.000; + let _ = 16_777_219f32; + let _: f32 = -16_777_219.0; + let _: f64 = 9_007_199_254_740_993.0; + let _: f64 = 9_007_199_254_740_993.; + let _: f64 = 9_007_199_254_740_993.00; + let _ = 9_007_199_254_740_993f64; + let _: f64 = -9_007_199_254_740_993.0; + + // Lossless whole number float literals + let _: f32 = 16_777_216.0; + let _: f32 = 16_777_218.0; + let _: f32 = 16_777_220.0; + let _: f32 = -16_777_216.0; + let _: f32 = -16_777_220.0; + let _: f64 = 16_777_217.0; + let _: f64 = -16_777_217.0; + let _: f64 = 9_007_199_254_740_992.0; + let _: f64 = -9_007_199_254_740_992.0; + + // Ignored whole number float literals + let _: f32 = 1e25; + let _: f32 = 1E25; + let _: f64 = 1e99; + let _: f64 = 1E99; + let _: f32 = 0.1; +} diff --git a/tests/ui/lossy_float_literal.stderr b/tests/ui/lossy_float_literal.stderr new file mode 100644 index 000000000000..d2193c0c8195 --- /dev/null +++ b/tests/ui/lossy_float_literal.stderr @@ -0,0 +1,70 @@ +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/lossy_float_literal.rs:6:18 + | +LL | let _: f32 = 16_777_217.0; + | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_216.0` + | + = note: `-D clippy::lossy-float-literal` implied by `-D warnings` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/lossy_float_literal.rs:7:18 + | +LL | let _: f32 = 16_777_219.0; + | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/lossy_float_literal.rs:8:18 + | +LL | let _: f32 = 16_777_219.; + | ^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/lossy_float_literal.rs:9:18 + | +LL | let _: f32 = 16_777_219.000; + | ^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/lossy_float_literal.rs:10:13 + | +LL | let _ = 16_777_219f32; + | ^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220_f32` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/lossy_float_literal.rs:11:19 + | +LL | let _: f32 = -16_777_219.0; + | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/lossy_float_literal.rs:12:18 + | +LL | let _: f64 = 9_007_199_254_740_993.0; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/lossy_float_literal.rs:13:18 + | +LL | let _: f64 = 9_007_199_254_740_993.; + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/lossy_float_literal.rs:14:18 + | +LL | let _: f64 = 9_007_199_254_740_993.00; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/lossy_float_literal.rs:15:13 + | +LL | let _ = 9_007_199_254_740_993f64; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992_f64` + +error: literal cannot be represented as the underlying type without loss of precision + --> $DIR/lossy_float_literal.rs:16:19 + | +LL | let _: f64 = -9_007_199_254_740_993.0; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` + +error: aborting due to 11 previous errors + From 8abe4365f3eab021bde47ef9ffebfb573918729d Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 21 Feb 2020 16:24:58 +0900 Subject: [PATCH 115/243] Use generator own DefId --- clippy_lints/src/doc.rs | 2 +- tests/ui/crashes/ice-5207.rs | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 tests/ui/crashes/ice-5207.rs diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 2968daa54b41..9b8664c13206 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -234,7 +234,7 @@ fn lint_for_missing_headers<'a, 'tcx>( if implements_trait(cx, ret_ty, future, &[]); if let ty::Opaque(_, subs) = ret_ty.kind; if let Some(gen) = subs.types().next(); - if let ty::Generator(_, subs, _) = gen.kind; + if let ty::Generator(def_id, subs, _) = gen.kind; if match_type(cx, subs.as_generator().return_ty(def_id, cx.tcx), &paths::RESULT); then { span_lint( diff --git a/tests/ui/crashes/ice-5207.rs b/tests/ui/crashes/ice-5207.rs new file mode 100644 index 000000000000..1b20c9defac8 --- /dev/null +++ b/tests/ui/crashes/ice-5207.rs @@ -0,0 +1,7 @@ +// edition:2018 + +// Regression test for https://github.com/rust-lang/rust-clippy/issues/5207 + +pub async fn bar<'a, T: 'a>(_: T) {} + +fn main() {} From 8a572a540af53bee712bc50a9d882a1c1376174c Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 7 Jan 2020 17:53:33 +0100 Subject: [PATCH 116/243] Add tests for wildcard_imports lint --- tests/ui/auxiliary/wildcard_imports_helper.rs | 21 +++ tests/ui/wildcard_imports.fixed | 137 ++++++++++++++++++ tests/ui/wildcard_imports.rs | 137 ++++++++++++++++++ tests/ui/wildcard_imports.stderr | 82 +++++++++++ 4 files changed, 377 insertions(+) create mode 100644 tests/ui/auxiliary/wildcard_imports_helper.rs create mode 100644 tests/ui/wildcard_imports.fixed create mode 100644 tests/ui/wildcard_imports.rs create mode 100644 tests/ui/wildcard_imports.stderr diff --git a/tests/ui/auxiliary/wildcard_imports_helper.rs b/tests/ui/auxiliary/wildcard_imports_helper.rs new file mode 100644 index 000000000000..414477aedd78 --- /dev/null +++ b/tests/ui/auxiliary/wildcard_imports_helper.rs @@ -0,0 +1,21 @@ +pub use crate::extern_exports::*; + +pub fn extern_foo() {} +pub fn extern_bar() {} + +pub struct ExternA; + +pub mod inner { + pub mod inner_for_self_import { + pub fn inner_extern_foo() {} + pub fn inner_extern_bar() {} + } +} + +mod extern_exports { + pub fn extern_exported() {} + pub struct ExternExportedStruct; + pub enum ExternExportedEnum { + A, + } +} diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed new file mode 100644 index 000000000000..97c8c6068e55 --- /dev/null +++ b/tests/ui/wildcard_imports.fixed @@ -0,0 +1,137 @@ +// run-rustfix +// aux-build:wildcard_imports_helper.rs + +#![warn(clippy::wildcard_imports)] +#![allow(unused)] +#![warn(unused_imports)] + +extern crate wildcard_imports_helper; + +use crate::fn_mod::foo; +use crate::mod_mod::inner_mod; +use crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}; +#[macro_use] +use crate::struct_mod::{A, inner_struct_mod}; + +#[allow(unused_imports)] +use wildcard_imports_helper::inner::inner_for_self_import; +use wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar; +use wildcard_imports_helper::{ExternA, extern_foo}; + +mod fn_mod { + pub fn foo() {} +} + +mod mod_mod { + pub mod inner_mod { + pub fn foo() {} + } +} + +mod multi_fn_mod { + pub fn multi_foo() {} + pub fn multi_bar() {} + pub fn multi_baz() {} + pub mod multi_inner_mod { + pub fn foo() {} + } +} + +mod struct_mod { + pub struct A; + pub struct B; + pub mod inner_struct_mod { + pub struct C; + } + + #[macro_export] + macro_rules! double_struct_import_test { + () => { + let _ = A; + }; + } +} + +fn main() { + foo(); + multi_foo(); + multi_bar(); + multi_inner_mod::foo(); + inner_mod::foo(); + extern_foo(); + inner_extern_bar(); + + let _ = A; + let _ = inner_struct_mod::C; + let _ = ExternA; + + double_struct_import_test!(); + double_struct_import_test!(); +} + +mod in_fn_test { + pub use self::inner_exported::*; + #[allow(unused_imports)] + pub(crate) use self::inner_exported2::*; + + fn test_intern() { + use crate::fn_mod::foo; + + foo(); + } + + fn test_extern() { + use wildcard_imports_helper::inner::inner_for_self_import::{self, inner_extern_foo}; + use wildcard_imports_helper::{ExternA, extern_foo}; + + inner_for_self_import::inner_extern_foo(); + inner_extern_foo(); + + extern_foo(); + + let _ = ExternA; + } + + fn test_inner_nested() { + use self::{inner::inner_foo, inner2::inner_bar}; + + inner_foo(); + inner_bar(); + } + + fn test_extern_reexported() { + use wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}; + + extern_exported(); + let _ = ExternExportedStruct; + let _ = ExternExportedEnum::A; + } + + mod inner_exported { + pub fn exported() {} + pub struct ExportedStruct; + pub enum ExportedEnum { + A, + } + } + + mod inner_exported2 { + pub(crate) fn exported2() {} + } + + mod inner { + pub fn inner_foo() {} + } + + mod inner2 { + pub fn inner_bar() {} + } +} + +fn test_reexported() { + use crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}; + + exported(); + let _ = ExportedStruct; + let _ = ExportedEnum::A; +} diff --git a/tests/ui/wildcard_imports.rs b/tests/ui/wildcard_imports.rs new file mode 100644 index 000000000000..045356672e3a --- /dev/null +++ b/tests/ui/wildcard_imports.rs @@ -0,0 +1,137 @@ +// run-rustfix +// aux-build:wildcard_imports_helper.rs + +#![warn(clippy::wildcard_imports)] +#![allow(unused)] +#![warn(unused_imports)] + +extern crate wildcard_imports_helper; + +use crate::fn_mod::*; +use crate::mod_mod::*; +use crate::multi_fn_mod::*; +#[macro_use] +use crate::struct_mod::*; + +#[allow(unused_imports)] +use wildcard_imports_helper::inner::inner_for_self_import; +use wildcard_imports_helper::inner::inner_for_self_import::*; +use wildcard_imports_helper::*; + +mod fn_mod { + pub fn foo() {} +} + +mod mod_mod { + pub mod inner_mod { + pub fn foo() {} + } +} + +mod multi_fn_mod { + pub fn multi_foo() {} + pub fn multi_bar() {} + pub fn multi_baz() {} + pub mod multi_inner_mod { + pub fn foo() {} + } +} + +mod struct_mod { + pub struct A; + pub struct B; + pub mod inner_struct_mod { + pub struct C; + } + + #[macro_export] + macro_rules! double_struct_import_test { + () => { + let _ = A; + }; + } +} + +fn main() { + foo(); + multi_foo(); + multi_bar(); + multi_inner_mod::foo(); + inner_mod::foo(); + extern_foo(); + inner_extern_bar(); + + let _ = A; + let _ = inner_struct_mod::C; + let _ = ExternA; + + double_struct_import_test!(); + double_struct_import_test!(); +} + +mod in_fn_test { + pub use self::inner_exported::*; + #[allow(unused_imports)] + pub(crate) use self::inner_exported2::*; + + fn test_intern() { + use crate::fn_mod::*; + + foo(); + } + + fn test_extern() { + use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; + use wildcard_imports_helper::*; + + inner_for_self_import::inner_extern_foo(); + inner_extern_foo(); + + extern_foo(); + + let _ = ExternA; + } + + fn test_inner_nested() { + use self::{inner::*, inner2::*}; + + inner_foo(); + inner_bar(); + } + + fn test_extern_reexported() { + use wildcard_imports_helper::*; + + extern_exported(); + let _ = ExternExportedStruct; + let _ = ExternExportedEnum::A; + } + + mod inner_exported { + pub fn exported() {} + pub struct ExportedStruct; + pub enum ExportedEnum { + A, + } + } + + mod inner_exported2 { + pub(crate) fn exported2() {} + } + + mod inner { + pub fn inner_foo() {} + } + + mod inner2 { + pub fn inner_bar() {} + } +} + +fn test_reexported() { + use crate::in_fn_test::*; + + exported(); + let _ = ExportedStruct; + let _ = ExportedEnum::A; +} diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr new file mode 100644 index 000000000000..111481e52d03 --- /dev/null +++ b/tests/ui/wildcard_imports.stderr @@ -0,0 +1,82 @@ +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:10:5 + | +LL | use crate::fn_mod::*; + | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` + | + = note: `-D clippy::wildcard-imports` implied by `-D warnings` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:11:5 + | +LL | use crate::mod_mod::*; + | ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:12:5 + | +LL | use crate::multi_fn_mod::*; + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:14:5 + | +LL | use crate::struct_mod::*; + | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:18:5 + | +LL | use wildcard_imports_helper::inner::inner_for_self_import::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:19:5 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:78:13 + | +LL | use crate::fn_mod::*; + | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:84:75 + | +LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; + | ^ help: try: `inner_extern_foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:85:13 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:96:20 + | +LL | use self::{inner::*, inner2::*}; + | ^^^^^^^^ help: try: `inner::inner_foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:96:30 + | +LL | use self::{inner::*, inner2::*}; + | ^^^^^^^^^ help: try: `inner2::inner_bar` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:103:13 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:132:9 + | +LL | use crate::in_fn_test::*; + | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` + +error: aborting due to 13 previous errors + From ba1d50cec1d6dbfbd866381f0b793cbd9c617b1b Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 7 Jan 2020 17:53:56 +0100 Subject: [PATCH 117/243] Implement wildcard_imports lint --- clippy_lints/src/wildcard_imports.rs | 271 +++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 clippy_lints/src/wildcard_imports.rs diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs new file mode 100644 index 000000000000..70098f31aef7 --- /dev/null +++ b/clippy_lints/src/wildcard_imports.rs @@ -0,0 +1,271 @@ +use crate::utils::{in_macro, snippet_with_applicability, span_lint_and_sugg}; +use if_chain::if_chain; +use rustc::ty::DefIdTree; +use rustc_data_structures::fx::FxHashSet; +use rustc_errors::Applicability; +use rustc_hir::def_id::DefId; +use rustc_hir::intravisit::{walk_item, NestedVisitorMap, Visitor}; +use rustc_hir::*; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{symbol::Symbol, BytePos}; + +declare_clippy_lint! { + /// **What it does:** Checks for wildcard imports `use _::*`. + /// + /// **Why is this bad?** wildcard imports can polute the namespace. This is especially bad if + /// you try to import something through a wildcard, that already has been imported by name from + /// a different source: + /// + /// ```rust,ignore + /// use crate1::foo; // Imports a function named foo + /// use crate2::*; // Has a function named foo + /// + /// foo(); // Calls crate1::foo + /// ``` + /// + /// This can lead to confusing error messages at best and to unexpected behavior at worst. + /// + /// **Known problems:** If macros are imported through the wildcard, this macro is not included + /// by the suggestion and has to be added by hand. + /// + /// **Example:** + /// + /// Bad: + /// ```rust,ignore + /// use crate1::*; + /// + /// foo(); + /// ``` + /// + /// Good: + /// ```rust,ignore + /// use crate1::foo; + /// + /// foo(); + /// ``` + pub WILDCARD_IMPORTS, + pedantic, + "lint `use _::*` statements" +} + +declare_lint_pass!(WildcardImports => [WILDCARD_IMPORTS]); + +impl LateLintPass<'_, '_> for WildcardImports { + fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item<'_>) { + if item.vis.node.is_pub() || item.vis.node.is_pub_restricted() { + return; + } + if_chain! { + if !in_macro(item.span); + if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; + if let Some(def_id) = use_path.res.opt_def_id(); + then { + let hir = cx.tcx.hir(); + let parent_id = hir.get_parent_item(item.hir_id); + let (items, in_module) = if parent_id == CRATE_HIR_ID { + let items = hir + .krate() + .module + .item_ids + .iter() + .map(|item_id| hir.get(item_id.id)) + .filter_map(|node| { + if let Node::Item(item) = node { + Some(item) + } else { + None + } + }) + .collect(); + (items, true) + } else if let Node::Item(item) = hir.get(parent_id) { + (vec![item], false) + } else { + (vec![], false) + }; + + let mut import_used_visitor = ImportsUsedVisitor { + cx, + wildcard_def_id: def_id, + in_module, + used_imports: FxHashSet::default(), + }; + for item in items { + import_used_visitor.visit_item(item); + } + + if !import_used_visitor.used_imports.is_empty() { + let module_name = use_path + .segments + .iter() + .last() + .expect("path has at least one segment") + .ident + .name; + + let mut applicability = Applicability::MachineApplicable; + let import_source = snippet_with_applicability(cx, use_path.span, "..", &mut applicability); + let (span, braced_glob) = if import_source.is_empty() { + // This is a `_::{_, *}` import + // Probably it's `_::{self, *}`, in that case we don't want to suggest to + // import `self`. + // If it is something else, we also don't want to include `self` in the + // suggestion, since either it was imported through another use statement: + // ``` + // use foo::bar; + // use foo::bar::{baz, *}; + // ``` + // or it couldn't be used anywhere. + ( + use_path.span.with_hi(use_path.span.hi() + BytePos(1)), + true, + ) + } else { + ( + use_path.span.with_hi(use_path.span.hi() + BytePos(3)), + false, + ) + }; + + let imports_string = if import_used_visitor.used_imports.len() == 1 { + // We don't need to check for accidental suggesting the module name instead + // of `self` here, since if `used_imports.len() == 1`, and the only usage + // is `self`, then it's not through a `*` and if there is a `*`, it gets + // already linted by `unused_imports` of rustc. + import_used_visitor.used_imports.iter().next().unwrap().to_string() + } else { + let mut imports = import_used_visitor + .used_imports + .iter() + .filter_map(|import_name| { + if braced_glob && *import_name == module_name { + None + } else if *import_name == module_name { + Some("self".to_string()) + } else { + Some(import_name.to_string()) + } + }) + .collect::>(); + imports.sort(); + if braced_glob { + imports.join(", ") + } else { + format!("{{{}}}", imports.join(", ")) + } + }; + + let sugg = if import_source.is_empty() { + imports_string + } else { + format!("{}::{}", import_source, imports_string) + }; + + span_lint_and_sugg( + cx, + WILDCARD_IMPORTS, + span, + "usage of wildcard import", + "try", + sugg, + applicability, + ); + } + } + } + } +} + +struct ImportsUsedVisitor<'a, 'tcx> { + cx: &'a LateContext<'a, 'tcx>, + wildcard_def_id: def_id::DefId, + in_module: bool, + used_imports: FxHashSet, +} + +impl<'a, 'tcx> Visitor<'tcx> for ImportsUsedVisitor<'a, 'tcx> { + type Map = Map<'tcx>; + + fn visit_item(&mut self, item: &'tcx Item<'_>) { + match item.kind { + ItemKind::Use(..) => {}, + ItemKind::Mod(..) if self.in_module => {}, + ItemKind::Mod(..) => self.in_module = true, + _ => walk_item(self, item), + } + } + + fn visit_path(&mut self, path: &Path<'_>, _: HirId) { + if let Some(def_id) = self.first_path_segment_def_id(path) { + // Check if the function/enum/... was exported + if let Some(exports) = self.cx.tcx.module_exports(self.wildcard_def_id) { + for export in exports { + if let Some(export_def_id) = export.res.opt_def_id() { + if export_def_id == def_id { + self.used_imports.insert( + path.segments + .iter() + .next() + .expect("path has at least one segment") + .ident + .name, + ); + return; + } + } + } + } + + // Check if it is directly in the module + if let Some(parent_def_id) = self.cx.tcx.parent(def_id) { + if self.wildcard_def_id == parent_def_id { + self.used_imports.insert( + path.segments + .iter() + .next() + .expect("path has at least one segment") + .ident + .name, + ); + } + } + } + } + + fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + NestedVisitorMap::All(&self.cx.tcx.hir()) + } +} + +impl ImportsUsedVisitor<'_, '_> { + fn skip_def_id(&self, def_id: DefId) -> DefId { + let def_key = self.cx.tcx.def_key(def_id); + match def_key.disambiguated_data.data { + DefPathData::Ctor => { + if let Some(def_id) = self.cx.tcx.parent(def_id) { + self.skip_def_id(def_id) + } else { + def_id + } + }, + _ => def_id, + } + } + + fn first_path_segment_def_id(&self, path: &Path<'_>) -> Option { + path.res.opt_def_id().and_then(|mut def_id| { + def_id = self.skip_def_id(def_id); + for _ in path.segments.iter().skip(1) { + def_id = self.skip_def_id(def_id); + if let Some(parent_def_id) = self.cx.tcx.parent(def_id) { + def_id = parent_def_id; + } else { + return None; + } + } + + Some(def_id) + }) + } +} From 4229dbcf335fa7a11b5566d9e916384bf9739c34 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 7 Jan 2020 17:54:08 +0100 Subject: [PATCH 118/243] Run update_lints --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 4 ++++ src/lintlist/mod.rs | 9 ++++++++- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05ebe97d7b01..4e99342e4a42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1419,6 +1419,7 @@ Released 2018-09-13 [`while_let_on_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator [`wildcard_dependencies`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_dependencies [`wildcard_enum_match_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_enum_match_arm +[`wildcard_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports [`wildcard_in_or_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_in_or_patterns [`write_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#write_literal [`write_with_newline`]: https://rust-lang.github.io/rust-clippy/master/index.html#write_with_newline diff --git a/README.md b/README.md index f2ffea7d23cf..3103f9608398 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 356 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 357 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 325f07eb6cf6..77d33e6a0db6 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -311,6 +311,7 @@ pub mod unwrap; pub mod use_self; pub mod vec; pub mod wildcard_dependencies; +pub mod wildcard_imports; pub mod write; pub mod zero_div_zero; // end lints modules, do not remove this comment, it’s used in `update_lints` @@ -813,6 +814,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &use_self::USE_SELF, &vec::USELESS_VEC, &wildcard_dependencies::WILDCARD_DEPENDENCIES, + &wildcard_imports::WILDCARD_IMPORTS, &write::PRINTLN_EMPTY_STRING, &write::PRINT_LITERAL, &write::PRINT_STDOUT, @@ -1009,6 +1011,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: let max_struct_bools = conf.max_struct_bools; store.register_early_pass(move || box excessive_bools::ExcessiveBools::new(max_struct_bools, max_fn_params_bools)); store.register_early_pass(|| box option_env_unwrap::OptionEnvUnwrap); + store.register_late_pass(|| box wildcard_imports::WildcardImports); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1105,6 +1108,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&unicode::NON_ASCII_LITERAL), LintId::of(&unicode::UNICODE_NOT_NFC), LintId::of(&unused_self::UNUSED_SELF), + LintId::of(&wildcard_imports::WILDCARD_IMPORTS), ]); store.register_group(true, "clippy::internal", Some("clippy_internal"), vec![ diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 5fdcf08072db..6f6674488b54 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -6,7 +6,7 @@ pub use lint::Lint; pub use lint::LINT_LEVELS; // begin lint list, do not remove this comment, it’s used in `update_lints` -pub const ALL_LINTS: [Lint; 356] = [ +pub const ALL_LINTS: [Lint; 357] = [ Lint { name: "absurd_extreme_comparisons", group: "correctness", @@ -2415,6 +2415,13 @@ pub const ALL_LINTS: [Lint; 356] = [ deprecation: None, module: "matches", }, + Lint { + name: "wildcard_imports", + group: "pedantic", + desc: "lint `use _::*` statements", + deprecation: None, + module: "wildcard_imports", + }, Lint { name: "wildcard_in_or_patterns", group: "complexity", From 3f5ed285249b7222d05051b16c97e25b7bbd086d Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 9 Jan 2020 18:12:54 +0100 Subject: [PATCH 119/243] Let's do it the easy way Queries are cool, but too hard to find. --- clippy_lints/src/wildcard_imports.rs | 242 +++++---------------------- 1 file changed, 40 insertions(+), 202 deletions(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 70098f31aef7..597552f033eb 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -1,14 +1,10 @@ use crate::utils::{in_macro, snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; -use rustc::ty::DefIdTree; -use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::{walk_item, NestedVisitorMap, Visitor}; use rustc_hir::*; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{symbol::Symbol, BytePos}; +use rustc_span::BytePos; declare_clippy_lint! { /// **What it does:** Checks for wildcard imports `use _::*`. @@ -59,213 +55,55 @@ impl LateLintPass<'_, '_> for WildcardImports { if_chain! { if !in_macro(item.span); if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; - if let Some(def_id) = use_path.res.opt_def_id(); + let used_imports = cx.tcx.names_imported_by_glob_use(item.hir_id.owner_def_id()); + if !used_imports.is_empty(); // Already handled by `unused_imports` then { - let hir = cx.tcx.hir(); - let parent_id = hir.get_parent_item(item.hir_id); - let (items, in_module) = if parent_id == CRATE_HIR_ID { - let items = hir - .krate() - .module - .item_ids - .iter() - .map(|item_id| hir.get(item_id.id)) - .filter_map(|node| { - if let Node::Item(item) = node { - Some(item) - } else { - None - } - }) - .collect(); - (items, true) - } else if let Node::Item(item) = hir.get(parent_id) { - (vec![item], false) + let mut applicability = Applicability::MachineApplicable; + let import_source = snippet_with_applicability(cx, use_path.span, "..", &mut applicability); + let (span, braced_glob) = if import_source.is_empty() { + // This is a `_::{_, *}` import + ( + use_path.span.with_hi(use_path.span.hi() + BytePos(1)), + true, + ) } else { - (vec![], false) + ( + use_path.span.with_hi(use_path.span.hi() + BytePos(3)), + false, + ) }; - let mut import_used_visitor = ImportsUsedVisitor { - cx, - wildcard_def_id: def_id, - in_module, - used_imports: FxHashSet::default(), - }; - for item in items { - import_used_visitor.visit_item(item); - } - - if !import_used_visitor.used_imports.is_empty() { - let module_name = use_path - .segments + let imports_string = if used_imports.len() == 1 { + used_imports.iter().next().unwrap().to_string() + } else { + let mut imports = used_imports .iter() - .last() - .expect("path has at least one segment") - .ident - .name; - - let mut applicability = Applicability::MachineApplicable; - let import_source = snippet_with_applicability(cx, use_path.span, "..", &mut applicability); - let (span, braced_glob) = if import_source.is_empty() { - // This is a `_::{_, *}` import - // Probably it's `_::{self, *}`, in that case we don't want to suggest to - // import `self`. - // If it is something else, we also don't want to include `self` in the - // suggestion, since either it was imported through another use statement: - // ``` - // use foo::bar; - // use foo::bar::{baz, *}; - // ``` - // or it couldn't be used anywhere. - ( - use_path.span.with_hi(use_path.span.hi() + BytePos(1)), - true, - ) - } else { - ( - use_path.span.with_hi(use_path.span.hi() + BytePos(3)), - false, - ) - }; - - let imports_string = if import_used_visitor.used_imports.len() == 1 { - // We don't need to check for accidental suggesting the module name instead - // of `self` here, since if `used_imports.len() == 1`, and the only usage - // is `self`, then it's not through a `*` and if there is a `*`, it gets - // already linted by `unused_imports` of rustc. - import_used_visitor.used_imports.iter().next().unwrap().to_string() - } else { - let mut imports = import_used_visitor - .used_imports - .iter() - .filter_map(|import_name| { - if braced_glob && *import_name == module_name { - None - } else if *import_name == module_name { - Some("self".to_string()) - } else { - Some(import_name.to_string()) - } - }) - .collect::>(); - imports.sort(); - if braced_glob { - imports.join(", ") - } else { - format!("{{{}}}", imports.join(", ")) - } - }; - - let sugg = if import_source.is_empty() { - imports_string + .map(ToString::to_string) + .collect::>(); + imports.sort(); + if braced_glob { + imports.join(", ") } else { - format!("{}::{}", import_source, imports_string) - }; - - span_lint_and_sugg( - cx, - WILDCARD_IMPORTS, - span, - "usage of wildcard import", - "try", - sugg, - applicability, - ); - } - } - } - } -} - -struct ImportsUsedVisitor<'a, 'tcx> { - cx: &'a LateContext<'a, 'tcx>, - wildcard_def_id: def_id::DefId, - in_module: bool, - used_imports: FxHashSet, -} - -impl<'a, 'tcx> Visitor<'tcx> for ImportsUsedVisitor<'a, 'tcx> { - type Map = Map<'tcx>; - - fn visit_item(&mut self, item: &'tcx Item<'_>) { - match item.kind { - ItemKind::Use(..) => {}, - ItemKind::Mod(..) if self.in_module => {}, - ItemKind::Mod(..) => self.in_module = true, - _ => walk_item(self, item), - } - } - - fn visit_path(&mut self, path: &Path<'_>, _: HirId) { - if let Some(def_id) = self.first_path_segment_def_id(path) { - // Check if the function/enum/... was exported - if let Some(exports) = self.cx.tcx.module_exports(self.wildcard_def_id) { - for export in exports { - if let Some(export_def_id) = export.res.opt_def_id() { - if export_def_id == def_id { - self.used_imports.insert( - path.segments - .iter() - .next() - .expect("path has at least one segment") - .ident - .name, - ); - return; - } + format!("{{{}}}", imports.join(", ")) } - } - } - - // Check if it is directly in the module - if let Some(parent_def_id) = self.cx.tcx.parent(def_id) { - if self.wildcard_def_id == parent_def_id { - self.used_imports.insert( - path.segments - .iter() - .next() - .expect("path has at least one segment") - .ident - .name, - ); - } - } - } - } - - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.cx.tcx.hir()) - } -} + }; -impl ImportsUsedVisitor<'_, '_> { - fn skip_def_id(&self, def_id: DefId) -> DefId { - let def_key = self.cx.tcx.def_key(def_id); - match def_key.disambiguated_data.data { - DefPathData::Ctor => { - if let Some(def_id) = self.cx.tcx.parent(def_id) { - self.skip_def_id(def_id) + let sugg = if import_source.is_empty() { + imports_string } else { - def_id - } - }, - _ => def_id, - } - } + format!("{}::{}", import_source, imports_string) + }; - fn first_path_segment_def_id(&self, path: &Path<'_>) -> Option { - path.res.opt_def_id().and_then(|mut def_id| { - def_id = self.skip_def_id(def_id); - for _ in path.segments.iter().skip(1) { - def_id = self.skip_def_id(def_id); - if let Some(parent_def_id) = self.cx.tcx.parent(def_id) { - def_id = parent_def_id; - } else { - return None; - } + span_lint_and_sugg( + cx, + WILDCARD_IMPORTS, + span, + "usage of wildcard import", + "try", + sugg, + applicability, + ); } - - Some(def_id) - }) + } } } From 06a6189376975ddff0d8db2fb20ab407066357b4 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 14 Jan 2020 13:52:08 +0100 Subject: [PATCH 120/243] Move enum_glob_use lint into wildcard_imports pass --- clippy_lints/src/enum_glob_use.rs | 49 ---------------------------- clippy_lints/src/lib.rs | 6 ++-- clippy_lints/src/wildcard_imports.rs | 35 +++++++++++++++++--- src/lintlist/mod.rs | 2 +- tests/ui/enum_glob_use.fixed | 30 +++++++++++++++++ tests/ui/enum_glob_use.rs | 29 ++++++++-------- tests/ui/enum_glob_use.stderr | 20 ++++++++---- 7 files changed, 92 insertions(+), 79 deletions(-) delete mode 100644 clippy_lints/src/enum_glob_use.rs create mode 100644 tests/ui/enum_glob_use.fixed diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs deleted file mode 100644 index 4ffc73961a8c..000000000000 --- a/clippy_lints/src/enum_glob_use.rs +++ /dev/null @@ -1,49 +0,0 @@ -//! lint on `use`ing all variants of an enum - -use crate::utils::span_lint; -use rustc_hir::def::{DefKind, Res}; -use rustc_hir::*; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::Span; - -declare_clippy_lint! { - /// **What it does:** Checks for `use Enum::*`. - /// - /// **Why is this bad?** It is usually better style to use the prefixed name of - /// an enumeration variant, rather than importing variants. - /// - /// **Known problems:** Old-style enumerations that prefix the variants are - /// still around. - /// - /// **Example:** - /// ```rust - /// use std::cmp::Ordering::*; - /// ``` - pub ENUM_GLOB_USE, - pedantic, - "use items that import all variants of an enum" -} - -declare_lint_pass!(EnumGlobUse => [ENUM_GLOB_USE]); - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EnumGlobUse { - fn check_mod(&mut self, cx: &LateContext<'a, 'tcx>, m: &'tcx Mod<'_>, _: Span, _: HirId) { - let map = cx.tcx.hir(); - // only check top level `use` statements - for item in m.item_ids { - lint_item(cx, map.expect_item(item.id)); - } - } -} - -fn lint_item(cx: &LateContext<'_, '_>, item: &Item<'_>) { - if item.vis.node.is_pub() { - return; // re-exports are fine - } - if let ItemKind::Use(ref path, UseKind::Glob) = item.kind { - if let Res::Def(DefKind::Enum, _) = path.res { - span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); - } - } -} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 77d33e6a0db6..2b5691f92555 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -197,7 +197,6 @@ pub mod else_if_without_else; pub mod empty_enum; pub mod entry; pub mod enum_clike; -pub mod enum_glob_use; pub mod enum_variants; pub mod eq_op; pub mod erasing_op; @@ -520,7 +519,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &empty_enum::EMPTY_ENUM, &entry::MAP_ENTRY, &enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT, - &enum_glob_use::ENUM_GLOB_USE, &enum_variants::ENUM_VARIANT_NAMES, &enum_variants::MODULE_INCEPTION, &enum_variants::MODULE_NAME_REPETITIONS, @@ -814,6 +812,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &use_self::USE_SELF, &vec::USELESS_VEC, &wildcard_dependencies::WILDCARD_DEPENDENCIES, + &wildcard_imports::ENUM_GLOB_USE, &wildcard_imports::WILDCARD_IMPORTS, &write::PRINTLN_EMPTY_STRING, &write::PRINT_LITERAL, @@ -837,7 +836,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move || box types::Types::new(vec_box_size_threshold)); store.register_late_pass(|| box booleans::NonminimalBool); store.register_late_pass(|| box eq_op::EqOp); - store.register_late_pass(|| box enum_glob_use::EnumGlobUse); store.register_late_pass(|| box enum_clike::UnportableVariant); store.register_late_pass(|| box float_literal::FloatLiteral); let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold; @@ -1064,7 +1062,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&doc::DOC_MARKDOWN), LintId::of(&doc::MISSING_ERRORS_DOC), LintId::of(&empty_enum::EMPTY_ENUM), - LintId::of(&enum_glob_use::ENUM_GLOB_USE), LintId::of(&enum_variants::MODULE_NAME_REPETITIONS), LintId::of(&enum_variants::PUB_ENUM_VARIANT_NAMES), LintId::of(&eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS), @@ -1108,6 +1105,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&unicode::NON_ASCII_LITERAL), LintId::of(&unicode::UNICODE_NOT_NFC), LintId::of(&unused_self::UNUSED_SELF), + LintId::of(&wildcard_imports::ENUM_GLOB_USE), LintId::of(&wildcard_imports::WILDCARD_IMPORTS), ]); diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 597552f033eb..584e7adfccc7 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -1,11 +1,32 @@ use crate::utils::{in_macro, snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{ + def::{DefKind, Res}, + Item, ItemKind, UseKind, +}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::BytePos; +declare_clippy_lint! { + /// **What it does:** Checks for `use Enum::*`. + /// + /// **Why is this bad?** It is usually better style to use the prefixed name of + /// an enumeration variant, rather than importing variants. + /// + /// **Known problems:** Old-style enumerations that prefix the variants are + /// still around. + /// + /// **Example:** + /// ```rust + /// use std::cmp::Ordering::*; + /// ``` + pub ENUM_GLOB_USE, + pedantic, + "use items that import all variants of an enum" +} + declare_clippy_lint! { /// **What it does:** Checks for wildcard imports `use _::*`. /// @@ -45,7 +66,7 @@ declare_clippy_lint! { "lint `use _::*` statements" } -declare_lint_pass!(WildcardImports => [WILDCARD_IMPORTS]); +declare_lint_pass!(WildcardImports => [ENUM_GLOB_USE, WILDCARD_IMPORTS]); impl LateLintPass<'_, '_> for WildcardImports { fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item<'_>) { @@ -94,11 +115,17 @@ impl LateLintPass<'_, '_> for WildcardImports { format!("{}::{}", import_source, imports_string) }; + let (lint, message) = if let Res::Def(DefKind::Enum, _) = use_path.res { + (ENUM_GLOB_USE, "usage of wildcard import for enum variants") + } else { + (WILDCARD_IMPORTS, "usage of wildcard import") + }; + span_lint_and_sugg( cx, - WILDCARD_IMPORTS, + lint, span, - "usage of wildcard import", + message, "try", sugg, applicability, diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 6f6674488b54..29b5a7ba08a2 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -460,7 +460,7 @@ pub const ALL_LINTS: [Lint; 357] = [ group: "pedantic", desc: "use items that import all variants of an enum", deprecation: None, - module: "enum_glob_use", + module: "wildcard_imports", }, Lint { name: "enum_variant_names", diff --git a/tests/ui/enum_glob_use.fixed b/tests/ui/enum_glob_use.fixed new file mode 100644 index 000000000000..a98216758bb9 --- /dev/null +++ b/tests/ui/enum_glob_use.fixed @@ -0,0 +1,30 @@ +// run-rustfix + +#![warn(clippy::enum_glob_use)] +#![allow(unused)] +#![warn(unused_imports)] + +use std::cmp::Ordering::Less; + +enum Enum { + Foo, +} + +use self::Enum::Foo; + +mod in_fn_test { + fn blarg() { + use crate::Enum::Foo; + + let _ = Foo; + } +} + +mod blurg { + pub use std::cmp::Ordering::*; // ok, re-export +} + +fn main() { + let _ = Foo; + let _ = Less; +} diff --git a/tests/ui/enum_glob_use.rs b/tests/ui/enum_glob_use.rs index e7b2526ca50b..5d929c9731d3 100644 --- a/tests/ui/enum_glob_use.rs +++ b/tests/ui/enum_glob_use.rs @@ -1,29 +1,30 @@ -#![warn(clippy::all, clippy::pedantic)] -#![allow(unused_imports, dead_code, clippy::missing_docs_in_private_items)] +// run-rustfix + +#![warn(clippy::enum_glob_use)] +#![allow(unused)] +#![warn(unused_imports)] use std::cmp::Ordering::*; enum Enum { - _Foo, + Foo, } use self::Enum::*; -fn blarg() { - use self::Enum::*; // ok, just for a function +mod in_fn_test { + fn blarg() { + use crate::Enum::*; + + let _ = Foo; + } } mod blurg { pub use std::cmp::Ordering::*; // ok, re-export } -mod tests { - use super::*; +fn main() { + let _ = Foo; + let _ = Less; } - -#[allow(non_snake_case)] -mod CamelCaseName {} - -use CamelCaseName::*; - -fn main() {} diff --git a/tests/ui/enum_glob_use.stderr b/tests/ui/enum_glob_use.stderr index a301703c2988..69531aed39bd 100644 --- a/tests/ui/enum_glob_use.stderr +++ b/tests/ui/enum_glob_use.stderr @@ -1,16 +1,22 @@ -error: don't use glob imports for enum variants - --> $DIR/enum_glob_use.rs:4:1 +error: usage of wildcard import for enum variants + --> $DIR/enum_glob_use.rs:7:5 | LL | use std::cmp::Ordering::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::cmp::Ordering::Less` | = note: `-D clippy::enum-glob-use` implied by `-D warnings` -error: don't use glob imports for enum variants - --> $DIR/enum_glob_use.rs:10:1 +error: usage of wildcard import for enum variants + --> $DIR/enum_glob_use.rs:13:5 | LL | use self::Enum::*; - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ help: try: `self::Enum::Foo` -error: aborting due to 2 previous errors +error: usage of wildcard import for enum variants + --> $DIR/enum_glob_use.rs:17:13 + | +LL | use crate::Enum::*; + | ^^^^^^^^^^^^^^ help: try: `crate::Enum::Foo` + +error: aborting due to 3 previous errors From f4f781d5cfd7a572006a8721c7998d13c378647d Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sun, 9 Feb 2020 12:23:13 +0100 Subject: [PATCH 121/243] Filter prelude glob imports --- clippy_lints/src/wildcard_imports.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 584e7adfccc7..3e8d28a22932 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -76,6 +76,8 @@ impl LateLintPass<'_, '_> for WildcardImports { if_chain! { if !in_macro(item.span); if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; + // don't lint prelude glob imports + if !use_path.segments.iter().last().map_or(false, |ps| ps.ident.as_str() == "prelude"); let used_imports = cx.tcx.names_imported_by_glob_use(item.hir_id.owner_def_id()); if !used_imports.is_empty(); // Already handled by `unused_imports` then { From b67764d5cb067aaa3ee53168855959465a8a7267 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sun, 9 Feb 2020 12:55:20 +0100 Subject: [PATCH 122/243] Add test for prelude import --- tests/ui/wildcard_imports.fixed | 10 ++++++++++ tests/ui/wildcard_imports.rs | 10 ++++++++++ tests/ui/wildcard_imports.stderr | 14 +++++++------- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index 97c8c6068e55..398c3b56572b 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -18,6 +18,16 @@ use wildcard_imports_helper::inner::inner_for_self_import; use wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar; use wildcard_imports_helper::{ExternA, extern_foo}; +use std::io::prelude::*; + +struct ReadFoo; + +impl Read for ReadFoo { + fn read(&mut self, _buf: &mut [u8]) -> std::io::Result { + Ok(0) + } +} + mod fn_mod { pub fn foo() {} } diff --git a/tests/ui/wildcard_imports.rs b/tests/ui/wildcard_imports.rs index 045356672e3a..10ab25e02ade 100644 --- a/tests/ui/wildcard_imports.rs +++ b/tests/ui/wildcard_imports.rs @@ -18,6 +18,16 @@ use wildcard_imports_helper::inner::inner_for_self_import; use wildcard_imports_helper::inner::inner_for_self_import::*; use wildcard_imports_helper::*; +use std::io::prelude::*; + +struct ReadFoo; + +impl Read for ReadFoo { + fn read(&mut self, _buf: &mut [u8]) -> std::io::Result { + Ok(0) + } +} + mod fn_mod { pub fn foo() {} } diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr index 111481e52d03..ca300fbaad49 100644 --- a/tests/ui/wildcard_imports.stderr +++ b/tests/ui/wildcard_imports.stderr @@ -37,43 +37,43 @@ LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:78:13 + --> $DIR/wildcard_imports.rs:88:13 | LL | use crate::fn_mod::*; | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:84:75 + --> $DIR/wildcard_imports.rs:94:75 | LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; | ^ help: try: `inner_extern_foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:85:13 + --> $DIR/wildcard_imports.rs:95:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:96:20 + --> $DIR/wildcard_imports.rs:106:20 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^ help: try: `inner::inner_foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:96:30 + --> $DIR/wildcard_imports.rs:106:30 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^^ help: try: `inner2::inner_bar` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:103:13 + --> $DIR/wildcard_imports.rs:113:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:132:9 + --> $DIR/wildcard_imports.rs:142:9 | LL | use crate::in_fn_test::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` From 8472ecda0f18a2b1045d4b8736e06e774ab1c73a Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 21 Feb 2020 09:39:38 +0100 Subject: [PATCH 123/243] Fix fallout --- clippy_dev/src/main.rs | 5 ++++- clippy_lints/src/approx_const.rs | 2 +- clippy_lints/src/as_conversions.rs | 2 +- clippy_lints/src/assertions_on_constants.rs | 2 +- clippy_lints/src/assign_ops.rs | 4 +++- clippy_lints/src/atomic_ordering.rs | 2 +- clippy_lints/src/attrs.rs | 6 +++-- clippy_lints/src/bit_mask.rs | 2 +- clippy_lints/src/blacklisted_name.rs | 2 +- clippy_lints/src/block_in_if_condition.rs | 4 ++-- clippy_lints/src/booleans.rs | 10 ++++----- clippy_lints/src/bytecount.rs | 2 +- clippy_lints/src/cargo_common_metadata.rs | 2 +- clippy_lints/src/checked_conversions.rs | 2 +- clippy_lints/src/cognitive_complexity.rs | 2 +- clippy_lints/src/comparison_chain.rs | 2 +- clippy_lints/src/consts.rs | 10 ++++----- clippy_lints/src/copies.rs | 2 +- clippy_lints/src/default_trait_access.rs | 2 +- clippy_lints/src/derive.rs | 2 +- clippy_lints/src/doc.rs | 8 ++++--- clippy_lints/src/double_comparison.rs | 2 +- clippy_lints/src/double_parens.rs | 2 +- clippy_lints/src/drop_bounds.rs | 2 +- clippy_lints/src/drop_forget_ref.rs | 2 +- clippy_lints/src/duration_subsec.rs | 2 +- clippy_lints/src/else_if_without_else.rs | 2 +- clippy_lints/src/empty_enum.rs | 2 +- clippy_lints/src/entry.rs | 2 +- clippy_lints/src/enum_clike.rs | 2 +- clippy_lints/src/enum_variants.rs | 2 +- clippy_lints/src/eq_op.rs | 2 +- clippy_lints/src/erasing_op.rs | 2 +- clippy_lints/src/escape.rs | 4 ++-- clippy_lints/src/eta_reduction.rs | 2 +- clippy_lints/src/eval_order_dependence.rs | 2 +- clippy_lints/src/explicit_write.rs | 2 +- clippy_lints/src/fallible_impl_from.rs | 2 +- clippy_lints/src/float_literal.rs | 2 +- clippy_lints/src/format.rs | 2 +- clippy_lints/src/formatting.rs | 2 +- clippy_lints/src/functions.rs | 6 ++--- clippy_lints/src/identity_conversion.rs | 2 +- clippy_lints/src/identity_op.rs | 2 +- clippy_lints/src/if_let_some_result.rs | 2 +- clippy_lints/src/if_not_else.rs | 2 +- clippy_lints/src/indexing_slicing.rs | 2 +- clippy_lints/src/infinite_iter.rs | 2 +- clippy_lints/src/inherent_impl.rs | 2 +- clippy_lints/src/inline_fn_without_body.rs | 2 +- clippy_lints/src/int_plus_one.rs | 2 +- clippy_lints/src/items_after_statements.rs | 2 +- clippy_lints/src/large_enum_variant.rs | 2 +- clippy_lints/src/large_stack_arrays.rs | 2 +- clippy_lints/src/len_zero.rs | 2 +- clippy_lints/src/let_underscore.rs | 2 +- clippy_lints/src/lifetimes.rs | 12 +++++++--- clippy_lints/src/literal_representation.rs | 2 +- clippy_lints/src/loops.rs | 9 +++++--- clippy_lints/src/matches.rs | 5 ++++- .../methods/manual_saturating_arithmetic.rs | 5 ++++- .../src/methods/option_map_unwrap_or.rs | 2 +- clippy_lints/src/minmax.rs | 2 +- clippy_lints/src/misc.rs | 5 ++++- clippy_lints/src/misc_early.rs | 5 ++++- clippy_lints/src/modulo_arithmetic.rs | 2 +- clippy_lints/src/mul_add.rs | 4 ++-- clippy_lints/src/multiple_crate_versions.rs | 2 +- clippy_lints/src/mut_reference.rs | 2 +- clippy_lints/src/needless_bool.rs | 6 ++--- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 2 +- clippy_lints/src/neg_multiply.rs | 2 +- clippy_lints/src/non_copy_const.rs | 2 +- clippy_lints/src/non_expressive_names.rs | 4 +++- clippy_lints/src/option_env_unwrap.rs | 2 +- .../src/overflow_check_conditional.rs | 2 +- clippy_lints/src/panic_unimplemented.rs | 2 +- clippy_lints/src/partialeq_ne_impl.rs | 2 +- clippy_lints/src/path_buf_push_overwrite.rs | 2 +- clippy_lints/src/precedence.rs | 6 ++--- clippy_lints/src/ptr.rs | 5 ++++- clippy_lints/src/question_mark.rs | 4 ++-- clippy_lints/src/ranges.rs | 2 +- clippy_lints/src/redundant_clone.rs | 2 +- clippy_lints/src/redundant_field_names.rs | 2 +- .../src/redundant_pattern_matching.rs | 2 +- .../src/redundant_static_lifetimes.rs | 2 +- clippy_lints/src/regex.rs | 6 ++--- clippy_lints/src/replace_consts.rs | 2 +- clippy_lints/src/serde_api.rs | 2 +- clippy_lints/src/shadow.rs | 7 ++++-- .../src/slow_vector_initialization.rs | 2 +- clippy_lints/src/strings.rs | 2 +- clippy_lints/src/swap.rs | 2 +- clippy_lints/src/trait_bounds.rs | 2 +- clippy_lints/src/transmute.rs | 2 +- .../src/trivially_copy_pass_by_ref.rs | 2 +- clippy_lints/src/try_err.rs | 2 +- clippy_lints/src/types.rs | 22 +++++++++++-------- clippy_lints/src/unicode.rs | 2 +- clippy_lints/src/unsafe_removed_from_name.rs | 2 +- clippy_lints/src/unwrap.rs | 4 ++-- clippy_lints/src/use_self.rs | 5 ++++- clippy_lints/src/utils/author.rs | 2 +- clippy_lints/src/utils/hir_utils.rs | 6 ++++- clippy_lints/src/utils/internal_lints.rs | 2 +- clippy_lints/src/utils/mod.rs | 9 +++++--- clippy_lints/src/utils/ptr.rs | 2 +- clippy_lints/src/utils/sugg.rs | 11 +++++++--- clippy_lints/src/utils/usage.rs | 4 ++-- clippy_lints/src/vec.rs | 2 +- clippy_lints/src/wildcard_dependencies.rs | 2 +- clippy_lints/src/write.rs | 6 +++-- clippy_lints/src/zero_div_zero.rs | 2 +- src/driver.rs | 4 ++-- src/main.rs | 2 +- 117 files changed, 219 insertions(+), 162 deletions(-) diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index ec0c33109ba9..901e663ded38 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -1,7 +1,10 @@ #![cfg_attr(feature = "deny-warnings", deny(warnings))] use clap::{App, Arg, SubCommand}; -use clippy_dev::*; +use clippy_dev::{ + gather_all, gen_changelog_lint_list, gen_deprecated, gen_lint_group_list, gen_modules_list, gen_register_lint_list, + replace_region_in_file, Lint, DOCS_LINK, +}; use std::path::Path; mod fmt; diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 51b6f2f0688f..042b83dc386d 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -1,5 +1,5 @@ use crate::utils::span_lint; -use rustc_hir::*; +use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol; diff --git a/clippy_lints/src/as_conversions.rs b/clippy_lints/src/as_conversions.rs index d90a0d67d5a5..5c584b18f4c3 100644 --- a/clippy_lints/src/as_conversions.rs +++ b/clippy_lints/src/as_conversions.rs @@ -1,7 +1,7 @@ use rustc::lint::in_external_macro; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::*; +use syntax::ast::{Expr, ExprKind}; use crate::utils::span_lint_and_help; diff --git a/clippy_lints/src/assertions_on_constants.rs b/clippy_lints/src/assertions_on_constants.rs index e399229b43ca..8a7a48aebf9b 100644 --- a/clippy_lints/src/assertions_on_constants.rs +++ b/clippy_lints/src/assertions_on_constants.rs @@ -2,7 +2,7 @@ use crate::consts::{constant, Constant}; use crate::utils::paths; use crate::utils::{is_direct_expn_of, is_expn_of, match_function_call, snippet_opt, span_lint_and_help}; use if_chain::if_chain; -use rustc_hir::*; +use rustc_hir::{Expr, ExprKind, PatKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use syntax::ast::LitKind; diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 7ad0ce232023..bc4e47340c69 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -231,7 +231,9 @@ fn lint_misrefactored_assign_op( #[must_use] fn is_commutative(op: hir::BinOpKind) -> bool { - use rustc_hir::BinOpKind::*; + use rustc_hir::BinOpKind::{ + Add, And, BitAnd, BitOr, BitXor, Div, Eq, Ge, Gt, Le, Lt, Mul, Ne, Or, Rem, Shl, Shr, Sub, + }; match op { Add | Mul | And | Or | BitXor | BitAnd | BitOr | Eq | Ne => true, Sub | Div | Rem | Shl | Shr | Lt | Le | Ge | Gt => false, diff --git a/clippy_lints/src/atomic_ordering.rs b/clippy_lints/src/atomic_ordering.rs index 178ee45298e3..871ca029b1aa 100644 --- a/clippy_lints/src/atomic_ordering.rs +++ b/clippy_lints/src/atomic_ordering.rs @@ -2,7 +2,7 @@ use crate::utils::{match_def_path, span_lint_and_help}; use if_chain::if_chain; use rustc::ty; use rustc_hir::def_id::DefId; -use rustc_hir::*; +use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 6f67acb29219..5c083cefc8d1 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -1,6 +1,6 @@ //! checks for attributes -use crate::reexport::*; +use crate::reexport::Name; use crate::utils::{ first_line_of_span, is_present_in_source, match_def_path, paths, snippet_opt, span_lint, span_lint_and_sugg, span_lint_and_then, without_block_comments, @@ -9,7 +9,9 @@ use if_chain::if_chain; use rustc::lint::in_external_macro; use rustc::ty; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{ + Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitItem, TraitItemKind, TraitMethod, +}; use rustc_lint::{CheckLintNameResult, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 926b1c63ad12..05f85e929614 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -3,7 +3,7 @@ use crate::utils::sugg::Sugg; use crate::utils::{span_lint, span_lint_and_then}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index cb68ba598868..6f26f031431d 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -1,6 +1,6 @@ use crate::utils::span_lint; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::*; +use rustc_hir::{Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 325e12617142..d004dcddfea0 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -1,10 +1,10 @@ -use crate::utils::*; +use crate::utils::{differing_macro_contexts, higher, snippet_block_with_applicability, span_lint, span_lint_and_sugg}; use matches::matches; use rustc::hir::map::Map; use rustc::lint::in_external_macro; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use rustc_hir::*; +use rustc_hir::{BlockCheckMode, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index d37f77cf6cc3..07b4f572dd54 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -5,8 +5,8 @@ use crate::utils::{ use if_chain::if_chain; use rustc::hir::map::Map; use rustc_errors::Applicability; -use rustc_hir::intravisit::*; -use rustc_hir::*; +use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor}; +use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; @@ -161,7 +161,7 @@ struct SuggestContext<'a, 'tcx, 'v> { impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { fn recurse(&mut self, suggestion: &Bool) -> Option<()> { - use quine_mc_cluskey::Bool::*; + use quine_mc_cluskey::Bool::{And, False, Not, Or, Term, True}; match suggestion { True => { self.output.push_str("true"); @@ -277,7 +277,7 @@ fn suggest(cx: &LateContext<'_, '_>, suggestion: &Bool, terminals: &[&Expr<'_>]) } fn simple_negate(b: Bool) -> Bool { - use quine_mc_cluskey::Bool::*; + use quine_mc_cluskey::Bool::{And, False, Not, Or, Term, True}; match b { True => False, False => True, @@ -325,7 +325,7 @@ fn terminal_stats(b: &Bool) -> Stats { &Term(n) => stats.terminals[n as usize] += 1, } } - use quine_mc_cluskey::Bool::*; + use quine_mc_cluskey::Bool::{And, False, Not, Or, Term, True}; let mut stats = Stats::default(); recurse(b, &mut stats); stats diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 2adc3b429067..e8168cb7393a 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -5,7 +5,7 @@ use crate::utils::{ use if_chain::if_chain; use rustc::ty; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use syntax::ast::{Name, UintTy}; diff --git a/clippy_lints/src/cargo_common_metadata.rs b/clippy_lints/src/cargo_common_metadata.rs index ec53e08f50cd..9e0e9d7dd6a0 100644 --- a/clippy_lints/src/cargo_common_metadata.rs +++ b/clippy_lints/src/cargo_common_metadata.rs @@ -6,7 +6,7 @@ use crate::utils::span_lint; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::DUMMY_SP; -use syntax::ast::*; +use syntax::ast::Crate; declare_clippy_lint! { /// **What it does:** Checks to see if all common metadata is defined in diff --git a/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs index 88df0772ae5e..835f8b7f902a 100644 --- a/clippy_lints/src/checked_conversions.rs +++ b/clippy_lints/src/checked_conversions.rs @@ -3,7 +3,7 @@ use if_chain::if_chain; use rustc::lint::in_external_macro; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use syntax::ast::LitKind; diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs index 2b6315255016..ecae13a49708 100644 --- a/clippy_lints/src/cognitive_complexity.rs +++ b/clippy_lints/src/cognitive_complexity.rs @@ -2,7 +2,7 @@ use rustc::hir::map::Map; use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor}; -use rustc_hir::*; +use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/comparison_chain.rs b/clippy_lints/src/comparison_chain.rs index 684d3448ea43..e0c381ddbfc4 100644 --- a/clippy_lints/src/comparison_chain.rs +++ b/clippy_lints/src/comparison_chain.rs @@ -1,7 +1,7 @@ use crate::utils::{ get_trait_def_id, if_sequence, implements_trait, parent_node_is_if_expr, paths, span_lint_and_help, SpanlessEq, }; -use rustc_hir::*; +use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 7efc62d4c2e1..edfd2486be28 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -7,13 +7,13 @@ use rustc::ty::{self, Ty, TyCtxt}; use rustc::{bug, span_bug}; use rustc_data_structures::sync::Lrc; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::*; +use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, QPath, UnOp}; use rustc_lint::LateContext; use rustc_span::symbol::Symbol; use std::cmp::Ordering::{self, Equal}; use std::convert::TryInto; use std::hash::{Hash, Hasher}; -use syntax::ast::{FloatTy, LitKind}; +use syntax::ast::{FloatTy, LitFloatType, LitKind}; /// A `LitKind`-like enum to fold constant `Expr`s into. #[derive(Debug, Clone)] @@ -152,8 +152,6 @@ impl Constant { /// Parses a `LitKind` to a `Constant`. pub fn lit_to_constant(lit: &LitKind, ty: Option>) -> Constant { - use syntax::ast::*; - match *lit { LitKind::Str(ref is, _) => Constant::Str(is.to_string()), LitKind::Byte(b) => Constant::Int(u128::from(b)), @@ -277,7 +275,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { #[allow(clippy::cast_possible_wrap)] fn constant_not(&self, o: &Constant, ty: Ty<'_>) -> Option { - use self::Constant::*; + use self::Constant::{Bool, Int}; match *o { Bool(b) => Some(Bool(!b)), Int(value) => { @@ -293,7 +291,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } fn constant_negate(&self, o: &Constant, ty: Ty<'_>) -> Option { - use self::Constant::*; + use self::Constant::{Int, F32, F64}; match *o { Int(value) => { let ity = match ty.kind { diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index d2d20375dafa..996f80a757e7 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -2,7 +2,7 @@ use crate::utils::{get_parent_expr, higher, if_sequence, same_tys, snippet, span use crate::utils::{SpanlessEq, SpanlessHash}; use rustc::ty::Ty; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::*; +use rustc_hir::{Arm, Block, Expr, ExprKind, MatchSource, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::Symbol; diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index 0e1380df9216..f99e6d96e030 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -1,7 +1,7 @@ use if_chain::if_chain; use rustc::ty; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index efb44ab6dbb9..f130a69778f6 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -2,7 +2,7 @@ use crate::utils::paths; use crate::utils::{is_automatically_derived, is_copy, match_path, span_lint_and_then}; use if_chain::if_chain; use rustc::ty::{self, Ty}; -use rustc_hir::*; +use rustc_hir::{Item, ItemKind, TraitRef}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 9b8664c13206..be65fd21a68e 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -350,7 +350,7 @@ fn check_attrs<'a>(cx: &LateContext<'_, '_>, valid_idents: &FxHashSet, a let parser = pulldown_cmark::Parser::new(&doc).into_offset_iter(); // Iterate over all `Events` and combine consecutive events into one let events = parser.coalesce(|previous, current| { - use pulldown_cmark::Event::*; + use pulldown_cmark::Event::Text; let previous_range = previous.1; let current_range = current.1; @@ -374,8 +374,10 @@ fn check_doc<'a, Events: Iterator, Range DocHeaders { // true if a safety header was found - use pulldown_cmark::Event::*; - use pulldown_cmark::Tag::*; + use pulldown_cmark::Event::{ + Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text, + }; + use pulldown_cmark::Tag::{CodeBlock, Heading, Link}; let mut headers = DocHeaders { safety: false, diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index 934e3ccdf87c..44f85d1ea6e1 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -1,7 +1,7 @@ //! Lint on unnecessary double comparisons. Some examples: use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index d08981e8badc..c4c4758ebb78 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -1,7 +1,7 @@ use crate::utils::span_lint; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::*; +use syntax::ast::{Expr, ExprKind}; declare_clippy_lint! { /// **What it does:** Checks for unnecessary double parentheses. diff --git a/clippy_lints/src/drop_bounds.rs b/clippy_lints/src/drop_bounds.rs index 1d445a153231..f49668082791 100644 --- a/clippy_lints/src/drop_bounds.rs +++ b/clippy_lints/src/drop_bounds.rs @@ -1,6 +1,6 @@ use crate::utils::{match_def_path, paths, span_lint}; use if_chain::if_chain; -use rustc_hir::*; +use rustc_hir::{GenericBound, GenericParam, WhereBoundPredicate, WherePredicate}; use rustc_lint::LateLintPass; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 29351deea286..bd9bdfef090b 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,7 +1,7 @@ use crate::utils::{is_copy, match_def_path, paths, qpath_res, span_lint_and_note}; use if_chain::if_chain; use rustc::ty; -use rustc_hir::*; +use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index 366996fb381b..b35a8facf8b9 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -1,6 +1,6 @@ use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index b87900180f26..c41c5aadbee7 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -3,7 +3,7 @@ use rustc::lint::in_external_macro; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::*; +use syntax::ast::{Expr, ExprKind}; use crate::utils::span_lint_and_help; diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index c43db68d20f2..010d208c9e79 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -1,7 +1,7 @@ //! lint when there is an enum with no variants use crate::utils::span_lint_and_then; -use rustc_hir::*; +use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index d32e78798afe..19da4c4bc9a5 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -5,7 +5,7 @@ use if_chain::if_chain; use rustc::hir::map::Map; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use rustc_hir::*; +use rustc_hir::{BorrowKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 2e14956ecd7b..e8063ac3006c 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -5,7 +5,7 @@ use crate::consts::{miri_to_const, Constant}; use crate::utils::span_lint; use rustc::ty; use rustc::ty::util::IntTypeExt; -use rustc_hir::*; +use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::convert::TryFrom; diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 75205f964008..0d14b8a75e8a 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -6,7 +6,7 @@ use rustc_lint::{EarlyContext, EarlyLintPass, Lint}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; -use syntax::ast::*; +use syntax::ast::{EnumDef, Item, ItemKind, VisibilityKind}; declare_clippy_lint! { /// **What it does:** Detects enumeration variants that are prefixed or suffixed diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index 01b04220a069..1df0bcc6b7e8 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -2,7 +2,7 @@ use crate::utils::{ implements_trait, in_macro, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq, }; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{BinOp, BinOpKind, BorrowKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs index e08e01c1d67e..3ff0506e28d0 100644 --- a/clippy_lints/src/erasing_op.rs +++ b/clippy_lints/src/erasing_op.rs @@ -1,4 +1,4 @@ -use rustc_hir::*; +use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 73bd7b3a143c..850c7f728bd2 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -1,12 +1,12 @@ use rustc::ty::layout::LayoutOf; use rustc::ty::{self, Ty}; use rustc_hir::intravisit; -use rustc_hir::{self, *}; +use rustc_hir::{self, Body, FnDecl, HirId, HirIdSet, ItemKind, Node}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; -use rustc_typeck::expr_use_visitor::*; +use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase}; use crate::utils::span_lint; diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 5ef933845005..8c324e09df55 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -3,7 +3,7 @@ use matches::matches; use rustc::lint::in_external_macro; use rustc::ty::{self, Ty}; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{def_id, Expr, ExprKind, Param, PatKind, QPath}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index f143c7462ad2..d6b847d1dbb1 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -3,7 +3,7 @@ use if_chain::if_chain; use rustc::hir::map::Map; use rustc::ty; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use rustc_hir::*; +use rustc_hir::{def, BinOpKind, Block, Expr, ExprKind, Guard, HirId, Local, Node, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 4aefa941dabe..a3005d8bd82a 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -1,7 +1,7 @@ use crate::utils::{is_expn_of, match_function_call, paths, span_lint, span_lint_and_sugg}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{BorrowKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use syntax::ast::LitKind; diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 87792b9fba47..19a122594cb7 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -48,7 +48,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FallibleImplFrom { fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_items: &[hir::ImplItemRef<'_>]) { use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; - use rustc_hir::*; + use rustc_hir::{Expr, ExprKind, ImplItemKind, QPath}; struct FindPanicUnwrap<'a, 'tcx> { lcx: &'a LateContext<'a, 'tcx>, diff --git a/clippy_lints/src/float_literal.rs b/clippy_lints/src/float_literal.rs index 8707259a2c88..18006f0534f0 100644 --- a/clippy_lints/src/float_literal.rs +++ b/clippy_lints/src/float_literal.rs @@ -7,7 +7,7 @@ use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::{f32, f64, fmt}; -use syntax::ast::*; +use syntax::ast::{FloatTy, LitFloatType, LitKind}; declare_clippy_lint! { /// **What it does:** Checks for float literals with a precision greater diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 36ed7c475ed3..6c80b6525bb5 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -5,7 +5,7 @@ use crate::utils::{ }; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, MatchSource, PatKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 31e924e36abe..0ab6b1242b3f 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -4,7 +4,7 @@ use rustc::lint::in_external_macro; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use syntax::ast::*; +use syntax::ast::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp}; declare_clippy_lint! { /// **What it does:** Checks for use of the non-existent `=*`, `=!` and `=-` diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index ce0bfea5160e..26b9f2cd613f 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -497,7 +497,7 @@ fn is_mutable_pat(cx: &LateContext<'_, '_>, pat: &hir::Pat<'_>, tys: &mut FxHash static KNOWN_WRAPPER_TYS: &[&[&str]] = &[&["alloc", "rc", "Rc"], &["std", "sync", "Arc"]]; fn is_mutable_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, span: Span, tys: &mut FxHashSet) -> bool { - use ty::TyKind::*; + use ty::TyKind::{Adt, Array, Bool, Char, Float, Int, RawPtr, Ref, Slice, Str, Tuple, Uint}; match ty.kind { // primitive types are never mutable Bool | Char | Int(_) | Uint(_) | Float(_) | Str => false, @@ -593,7 +593,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> { type Map = Map<'tcx>; fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) { - use hir::ExprKind::*; + use hir::ExprKind::{AddrOf, Assign, AssignOp, Call, MethodCall}; if self.mutates_static { return; @@ -631,7 +631,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> { } fn is_mutated_static(cx: &LateContext<'_, '_>, e: &hir::Expr<'_>) -> bool { - use hir::ExprKind::*; + use hir::ExprKind::{Field, Index, Path}; match e.kind { Path(ref qpath) => { diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs index 86478f093c9e..3d0734219846 100644 --- a/clippy_lints/src/identity_conversion.rs +++ b/clippy_lints/src/identity_conversion.rs @@ -2,7 +2,7 @@ use crate::utils::{ match_def_path, match_trait_method, paths, same_tys, snippet, snippet_with_macro_callsite, span_lint_and_then, }; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{Expr, ExprKind, HirId, MatchSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index 1896751ff6ff..abd546870aae 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -1,5 +1,5 @@ use rustc::ty; -use rustc_hir::*; +use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/if_let_some_result.rs b/clippy_lints/src/if_let_some_result.rs index a9826d586339..33e2471d5b8f 100644 --- a/clippy_lints/src/if_let_some_result.rs +++ b/clippy_lints/src/if_let_some_result.rs @@ -1,7 +1,7 @@ use crate::utils::{match_type, method_chain_args, paths, snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{print, Expr, ExprKind, MatchSource, PatKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index 8deed2142038..4689e24f368e 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -4,7 +4,7 @@ use rustc::lint::in_external_macro; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::*; +use syntax::ast::{BinOpKind, Expr, ExprKind, UnOp}; use crate::utils::span_lint_and_help; diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index ac9442e96078..f4a7b798521f 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -3,7 +3,7 @@ use crate::consts::{constant, Constant}; use crate::utils::{higher, span_lint, span_lint_and_help}; use rustc::ty; -use rustc_hir::*; +use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use syntax::ast::RangeLimits; diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index cee54488df48..cd989c0ea6f6 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -1,4 +1,4 @@ -use rustc_hir::*; +use rustc_hir::{BorrowKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index 058ee7265fbc..355e75d0d559 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -2,7 +2,7 @@ use crate::utils::{in_macro, span_lint_and_then}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::*; +use rustc_hir::{def_id, Crate, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::Span; diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index ed9a958f91b6..85c61ba23964 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -3,7 +3,7 @@ use crate::utils::span_lint_and_then; use crate::utils::sugg::DiagnosticBuilderExt; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{TraitItem, TraitItemKind, TraitMethod}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use syntax::ast::{Attribute, Name}; diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index cb2d62407ce8..c6734427dab7 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -3,7 +3,7 @@ use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::*; +use syntax::ast::{BinOpKind, Expr, ExprKind, Lit, LitKind}; use crate::utils::{snippet_opt, span_lint_and_then}; diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index 6d944ae8c33a..13da725393b3 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -4,7 +4,7 @@ use crate::utils::span_lint; use matches::matches; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::*; +use syntax::ast::{Block, ItemKind, StmtKind}; declare_clippy_lint! { /// **What it does:** Checks for items declared after some statement in a block. diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 0cd02f21238d..39c8c4cfa693 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -3,7 +3,7 @@ use crate::utils::{snippet_opt, span_lint_and_then}; use rustc::ty::layout::LayoutOf; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{Item, ItemKind, VariantData}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; diff --git a/clippy_lints/src/large_stack_arrays.rs b/clippy_lints/src/large_stack_arrays.rs index aa394c85e308..e08042bcbb26 100644 --- a/clippy_lints/src/large_stack_arrays.rs +++ b/clippy_lints/src/large_stack_arrays.rs @@ -1,6 +1,6 @@ use rustc::mir::interpret::ConstValue; use rustc::ty::{self, ConstKind}; -use rustc_hir::*; +use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index aa538a4be9de..821ca2fefa4e 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -3,7 +3,7 @@ use rustc::ty; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; -use rustc_hir::*; +use rustc_hir::{AssocItemKind, BinOpKind, Expr, ExprKind, ImplItemRef, Item, ItemKind, TraitItemRef}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::{Span, Spanned}; diff --git a/clippy_lints/src/let_underscore.rs b/clippy_lints/src/let_underscore.rs index c2a404ebee7c..5690a12141b9 100644 --- a/clippy_lints/src/let_underscore.rs +++ b/clippy_lints/src/let_underscore.rs @@ -1,6 +1,6 @@ use if_chain::if_chain; use rustc::lint::in_external_macro; -use rustc_hir::*; +use rustc_hir::{PatKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index f98021bca459..a120e3a7517f 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -3,15 +3,21 @@ use rustc::hir::map::Map; use rustc::lint::in_external_macro; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::intravisit::*; +use rustc_hir::intravisit::{ + walk_fn_decl, walk_generic_param, walk_generics, walk_param_bound, walk_ty, NestedVisitorMap, Visitor, +}; use rustc_hir::FnRetTy::Return; -use rustc_hir::*; +use rustc_hir::{ + BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem, ImplItemKind, Item, + ItemKind, Lifetime, LifetimeName, ParamName, QPath, TraitBoundModifier, TraitItem, TraitItemKind, TraitMethod, Ty, + TyKind, WhereClause, WherePredicate, +}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::symbol::kw; -use crate::reexport::*; +use crate::reexport::Name; use crate::utils::{last_path_segment, span_lint, trait_ref_of_method}; declare_clippy_lint! { diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 2419d42394e3..7c8001eebd47 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -7,7 +7,7 @@ use rustc::lint::in_external_macro; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; -use syntax::ast::*; +use syntax::ast::{Expr, ExprKind, Lit, LitFloatType, LitIntType, LitKind}; declare_clippy_lint! { /// **What it does:** Warns if a long integral or floating-point constant does diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 393fbd2aaefc..eb15b104bea6 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1,5 +1,5 @@ use crate::consts::{constant, Constant}; -use crate::reexport::*; +use crate::reexport::Name; use crate::utils::paths; use crate::utils::usage::{is_unused, mutated_variables}; use crate::utils::{ @@ -19,13 +19,16 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_block, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; -use rustc_hir::*; +use rustc_hir::{ + def_id, BinOpKind, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, GenericArg, HirId, LoopSource, + MatchSource, Mutability, Node, Pat, PatKind, QPath, Stmt, StmtKind, +}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::{BytePos, Symbol}; -use rustc_typeck::expr_use_visitor::*; +use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase}; use std::iter::{once, Iterator}; use std::mem; use syntax::ast; diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 72131084311a..d9d3611bc5a0 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -12,7 +12,10 @@ use rustc::lint::in_external_macro; use rustc::ty::{self, Ty}; use rustc_errors::Applicability; use rustc_hir::def::CtorKind; -use rustc_hir::*; +use rustc_hir::{ + print, Arm, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, Local, MatchSource, Mutability, PatKind, QPath, + RangeEnd, +}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/clippy_lints/src/methods/manual_saturating_arithmetic.rs index 4e3c95f9f739..19f3c4478616 100644 --- a/clippy_lints/src/methods/manual_saturating_arithmetic.rs +++ b/clippy_lints/src/methods/manual_saturating_arithmetic.rs @@ -23,7 +23,10 @@ pub fn lint(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, args: &[&[hir::Expr< }; if ty.is_signed() { - use self::{MinMax::*, Sign::*}; + use self::{ + MinMax::{Max, Min}, + Sign::{Neg, Pos}, + }; let sign = if let Some(sign) = lit_sign(arith_rhs) { sign diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index 80a937aadb06..4df963a4f796 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -4,7 +4,7 @@ use rustc::hir::map::Map; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_path, NestedVisitorMap, Visitor}; -use rustc_hir::{self, *}; +use rustc_hir::{self, HirId, Path}; use rustc_lint::LateContext; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index b3431c053783..b02c993de526 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -1,6 +1,6 @@ use crate::consts::{constant_simple, Constant}; use crate::utils::{match_def_path, paths, span_lint}; -use rustc_hir::*; +use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::cmp::Ordering; diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 583bdd43df83..85d66db83b15 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -3,7 +3,10 @@ use matches::matches; use rustc::ty; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; -use rustc_hir::*; +use rustc_hir::{ + def, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnDecl, HirId, Mutability, PatKind, Stmt, StmtKind, Ty, + TyKind, UnOp, +}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::{ExpnKind, Span}; diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 3f17ac3de228..6e89f35143be 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -9,7 +9,10 @@ use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use syntax::ast::*; +use syntax::ast::{ + Block, Expr, ExprKind, GenericParamKind, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind, + StmtKind, UnOp, +}; use syntax::visit::{walk_expr, FnKind, Visitor}; declare_clippy_lint! { diff --git a/clippy_lints/src/modulo_arithmetic.rs b/clippy_lints/src/modulo_arithmetic.rs index 238863e8c67b..7446b732c4b2 100644 --- a/clippy_lints/src/modulo_arithmetic.rs +++ b/clippy_lints/src/modulo_arithmetic.rs @@ -2,7 +2,7 @@ use crate::consts::{constant, Constant}; use crate::utils::{sext, span_lint_and_then}; use if_chain::if_chain; use rustc::ty::{self}; -use rustc_hir::*; +use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::fmt::Display; diff --git a/clippy_lints/src/mul_add.rs b/clippy_lints/src/mul_add.rs index 5de936634991..57e56d8f959a 100644 --- a/clippy_lints/src/mul_add.rs +++ b/clippy_lints/src/mul_add.rs @@ -1,9 +1,9 @@ use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::utils::*; +use crate::utils::{snippet, span_lint_and_sugg}; declare_clippy_lint! { /// **What it does:** Checks for expressions of the form `a * b + c` diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index d07b21bfa991..0bcce04e8120 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -4,7 +4,7 @@ use crate::utils::span_lint; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::DUMMY_SP; -use syntax::ast::*; +use syntax::ast::Crate; use itertools::Itertools; diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 2d70b65bb1ee..aeffcd34110e 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -1,7 +1,7 @@ use crate::utils::span_lint; use rustc::ty::subst::Subst; use rustc::ty::{self, Ty}; -use rustc_hir::*; +use rustc_hir::{print, BorrowKind, Expr, ExprKind, Mutability}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index db4012146dff..7282874fdbd0 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -5,7 +5,7 @@ use crate::utils::sugg::Sugg; use crate::utils::{higher, parent_node_is_if_expr, span_lint, span_lint_and_sugg}; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{BinOpKind, Block, Expr, ExprKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; @@ -62,7 +62,7 @@ declare_lint_pass!(NeedlessBool => [NEEDLESS_BOOL]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { - use self::Expression::*; + use self::Expression::{Bool, RetBool}; if let Some((ref pred, ref then_block, Some(ref else_expr))) = higher::if_block(&e) { let reduce = |ret, not| { let mut applicability = Applicability::MachineApplicable; @@ -191,7 +191,7 @@ fn check_comparison<'a, 'tcx>( right_false: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>, no_literal: Option<(impl FnOnce(Sugg<'a>, Sugg<'a>) -> Sugg<'a>, &str)>, ) { - use self::Expression::*; + use self::Expression::{Bool, Other}; if let ExprKind::Binary(_, ref left_side, ref right_side) = e.kind { let (l_ty, r_ty) = (cx.tables.expr_ty(left_side), cx.tables.expr_ty(right_side)); diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 7a0f3bdd3558..10782b9f3b4d 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -9,7 +9,7 @@ use rustc::ty::{self, TypeFoldable}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir::intravisit::FnKind; -use rustc_hir::*; +use rustc_hir::{BindingAnnotation, Body, FnDecl, GenericArg, HirId, ItemKind, Node, PatKind, QPath, TyKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits; use rustc_infer::traits::misc::can_type_implement_copy; diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index efe5f26c4239..65643d89df57 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -1,6 +1,6 @@ use if_chain::if_chain; use rustc::lint::in_external_macro; -use rustc_hir::*; +use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index bd4ada23762b..4681e990df88 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -1,5 +1,5 @@ use if_chain::if_chain; -use rustc_hir::*; +use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 48ffc113546f..46e26b326971 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -7,7 +7,7 @@ use std::ptr; use rustc::ty::adjustment::Adjust; use rustc::ty::{Ty, TypeFlags}; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::*; +use rustc_hir::{Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp}; use rustc_lint::{LateContext, LateLintPass, Lint}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{InnerSpan, Span, DUMMY_SP}; diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 5411e3246159..de5ae5d30322 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -4,7 +4,9 @@ use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use rustc_span::symbol::SymbolStr; use std::cmp::Ordering; -use syntax::ast::*; +use syntax::ast::{ + Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, Ident, Item, ItemKind, Local, Mac, Pat, PatKind, +}; use syntax::attr; use syntax::visit::{walk_block, walk_expr, walk_pat, Visitor}; diff --git a/clippy_lints/src/option_env_unwrap.rs b/clippy_lints/src/option_env_unwrap.rs index 1af7793499f6..6dc6893bf71c 100644 --- a/clippy_lints/src/option_env_unwrap.rs +++ b/clippy_lints/src/option_env_unwrap.rs @@ -2,7 +2,7 @@ use crate::utils::{is_direct_expn_of, span_lint_and_help}; use if_chain::if_chain; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::*; +use syntax::ast::{Expr, ExprKind}; declare_clippy_lint! { /// **What it does:** Checks for usage of `option_env!(...).unwrap()` and diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index df3f588f38a1..b90fdc232e72 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -1,6 +1,6 @@ use crate::utils::{span_lint, SpanlessEq}; use if_chain::if_chain; -use rustc_hir::*; +use rustc_hir::{BinOpKind, Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index b26ad1a5b45d..76a77e25de3c 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -1,6 +1,6 @@ use crate::utils::{is_direct_expn_of, is_expn_of, match_function_call, paths, span_lint}; use if_chain::if_chain; -use rustc_hir::*; +use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::Span; diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index dfd25f1c9db6..1445df41c452 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -1,6 +1,6 @@ use crate::utils::{is_automatically_derived, span_lint_hir}; use if_chain::if_chain; -use rustc_hir::*; +use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/path_buf_push_overwrite.rs b/clippy_lints/src/path_buf_push_overwrite.rs index adaf8bb77a20..775a8ad0b933 100644 --- a/clippy_lints/src/path_buf_push_overwrite.rs +++ b/clippy_lints/src/path_buf_push_overwrite.rs @@ -1,7 +1,7 @@ use crate::utils::{match_type, paths, span_lint_and_sugg, walk_ptrs_ty}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::path::{Component, Path}; diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index 27e67bbe718c..8ba4e10c9660 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -3,7 +3,7 @@ use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; -use syntax::ast::*; +use syntax::ast::{BinOpKind, Expr, ExprKind, LitKind, UnOp}; declare_clippy_lint! { /// **What it does:** Checks for operations where precedence may be unclear @@ -123,7 +123,7 @@ fn is_arith_expr(expr: &Expr) -> bool { #[must_use] fn is_bit_op(op: BinOpKind) -> bool { - use syntax::ast::BinOpKind::*; + use syntax::ast::BinOpKind::{BitAnd, BitOr, BitXor, Shl, Shr}; match op { BitXor | BitAnd | BitOr | Shl | Shr => true, _ => false, @@ -132,7 +132,7 @@ fn is_bit_op(op: BinOpKind) -> bool { #[must_use] fn is_arith_op(op: BinOpKind) -> bool { - use syntax::ast::BinOpKind::*; + use syntax::ast::BinOpKind::{Add, Div, Mul, Rem, Sub}; match op { Add | Sub | Mul | Div | Rem => true, _ => false, diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index d868253b85cd..c1aee94aa421 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -8,7 +8,10 @@ use crate::utils::{ use if_chain::if_chain; use rustc::ty; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{ + BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, HirId, ImplItem, ImplItemKind, Item, ItemKind, + Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitItem, TraitItemKind, TraitMethod, Ty, TyKind, +}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 46c4746d2f56..f21c2985d194 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -1,11 +1,11 @@ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::*; +use rustc_hir::{def, Block, Expr, ExprKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::utils::paths::*; +use crate::utils::paths::{OPTION, OPTION_NONE}; use crate::utils::sugg::Sugg; use crate::utils::{higher, match_def_path, match_type, span_lint_and_then, SpanlessEq}; diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 1be597877213..f1a93d508ce2 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -1,6 +1,6 @@ use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{BinOpKind, Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index e419ae09a3f9..ddb0c7484348 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -529,7 +529,7 @@ impl TypeVisitor<'_> for ContainsRegion { } fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) { - use rustc::mir::Rvalue::*; + use rustc::mir::Rvalue::{Aggregate, BinaryOp, Cast, CheckedBinaryOp, Repeat, UnaryOp, Use}; let mut visit_op = |op: &mir::Operand<'_>| match op { mir::Operand::Copy(p) | mir::Operand::Move(p) => visit(p.local), diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index 57349715c784..a839a023e525 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -2,7 +2,7 @@ use crate::utils::span_lint_and_sugg; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::*; +use syntax::ast::{Expr, ExprKind}; declare_clippy_lint! { /// **What it does:** Checks for fields in struct literals where shorthands diff --git a/clippy_lints/src/redundant_pattern_matching.rs b/clippy_lints/src/redundant_pattern_matching.rs index f0acd993480b..c8706c2b363b 100644 --- a/clippy_lints/src/redundant_pattern_matching.rs +++ b/clippy_lints/src/redundant_pattern_matching.rs @@ -1,6 +1,6 @@ use crate::utils::{match_qpath, paths, snippet, span_lint_and_then}; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{Arm, Expr, ExprKind, MatchSource, PatKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use syntax::ast::LitKind; diff --git a/clippy_lints/src/redundant_static_lifetimes.rs b/clippy_lints/src/redundant_static_lifetimes.rs index 9cebe310d5fe..98ec793de7c1 100644 --- a/clippy_lints/src/redundant_static_lifetimes.rs +++ b/clippy_lints/src/redundant_static_lifetimes.rs @@ -2,7 +2,7 @@ use crate::utils::{snippet, span_lint_and_then}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::*; +use syntax::ast::{Item, ItemKind, Ty, TyKind}; declare_clippy_lint! { /// **What it does:** Checks for constants and statics with an explicit `'static` lifetime. diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 5de0e441367a..028b89b39b94 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -2,7 +2,7 @@ use crate::consts::{constant, Constant}; use crate::utils::{is_expn_of, match_def_path, match_type, paths, span_lint, span_lint_and_help}; use if_chain::if_chain; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::*; +use rustc_hir::{Block, BorrowKind, Crate, Expr, ExprKind, HirId}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::{BytePos, Span}; @@ -145,8 +145,8 @@ fn const_str<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) -> Option< } fn is_trivial_regex(s: ®ex_syntax::hir::Hir) -> Option<&'static str> { - use regex_syntax::hir::Anchor::*; - use regex_syntax::hir::HirKind::*; + use regex_syntax::hir::Anchor::{EndText, StartText}; + use regex_syntax::hir::HirKind::{Alternation, Anchor, Concat, Empty, Literal}; let is_literal = |e: &[regex_syntax::hir::Hir]| { e.iter().all(|e| match *e.kind() { diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs index 66e1df72b25f..aca1ebbd5080 100644 --- a/clippy_lints/src/replace_consts.rs +++ b/clippy_lints/src/replace_consts.rs @@ -2,7 +2,7 @@ use crate::utils::{match_def_path, span_lint_and_sugg}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::*; +use rustc_hir::{Expr, ExprKind, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs index 63fdd599b51e..6820d1620bd1 100644 --- a/clippy_lints/src/serde_api.rs +++ b/clippy_lints/src/serde_api.rs @@ -1,5 +1,5 @@ use crate::utils::{get_trait_def_id, paths, span_lint}; -use rustc_hir::*; +use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 8e2ede04476e..0dc2705550b9 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -1,9 +1,12 @@ -use crate::reexport::*; +use crate::reexport::Name; use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then}; use rustc::lint::in_external_macro; use rustc::ty; use rustc_hir::intravisit::FnKind; -use rustc_hir::*; +use rustc_hir::{ + Block, Body, Expr, ExprKind, FnDecl, Guard, HirId, Local, MutTy, Pat, PatKind, Path, QPath, StmtKind, Ty, TyKind, + UnOp, +}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index 48d0e53d163e..71fcff33544e 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -4,7 +4,7 @@ use if_chain::if_chain; use rustc::hir::map::Map; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, NestedVisitorMap, Visitor}; -use rustc_hir::*; +use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, Lint}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::Symbol; diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index ffe7c13ec575..20ed4d9aac05 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -1,6 +1,6 @@ use rustc::lint::in_external_macro; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 7e699844ef23..a1f5dee2a9c3 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -7,7 +7,7 @@ use if_chain::if_chain; use matches::matches; use rustc::ty; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::Symbol; diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 858b505712d3..d343ec4a8483 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -1,6 +1,6 @@ use crate::utils::{in_macro, snippet, span_lint_and_help, SpanlessHash}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::*; +use rustc_hir::{GenericBound, Generics, WherePredicate}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index e6a9aa3c9a63..68c924cea475 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -4,7 +4,7 @@ use crate::utils::{ use if_chain::if_chain; use rustc::ty::{self, Ty}; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{Expr, ExprKind, GenericArg, Mutability, QPath, TyKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::borrow::Cow; diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 1bacb4683c38..e00bc2e090ae 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -8,7 +8,7 @@ use rustc::ty; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; -use rustc_hir::*; +use rustc_hir::{Body, FnDecl, HirId, ItemKind, MutTy, Mutability, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::Span; diff --git a/clippy_lints/src/try_err.rs b/clippy_lints/src/try_err.rs index 15f77d62201d..a6624408ce05 100644 --- a/clippy_lints/src/try_err.rs +++ b/clippy_lints/src/try_err.rs @@ -3,7 +3,7 @@ use if_chain::if_chain; use rustc::lint::in_external_macro; use rustc::ty::Ty; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{Arm, Expr, ExprKind, MatchSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index d23487b5b334..e9c0b0935fa9 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -12,7 +12,11 @@ use rustc::ty::{self, InferTy, Ty, TyCtxt, TypeckTables}; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; -use rustc_hir::*; +use rustc_hir::{ + BinOpKind, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericParamKind, HirId, ImplItem, + ImplItemKind, Item, ItemKind, Lifetime, Local, MatchSource, MutTy, Mutability, QPath, Stmt, StmtKind, TraitItem, + TraitItemKind, TraitMethod, TyKind, UnOp, +}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; use rustc_span::hygiene::{ExpnKind, MacroKind}; @@ -1679,9 +1683,9 @@ fn detect_absurd_comparison<'a, 'tcx>( lhs: &'tcx Expr<'_>, rhs: &'tcx Expr<'_>, ) -> Option<(ExtremeExpr<'tcx>, AbsurdComparisonResult)> { - use crate::types::AbsurdComparisonResult::*; - use crate::types::ExtremeType::*; - use crate::utils::comparisons::*; + use crate::types::AbsurdComparisonResult::{AlwaysFalse, AlwaysTrue, InequalityImpossible}; + use crate::types::ExtremeType::{Maximum, Minimum}; + use crate::utils::comparisons::{normalize_comparison, Rel}; // absurd comparison only makes sense on primitive types // primitive types don't implement comparison operators with each other @@ -1726,7 +1730,7 @@ fn detect_absurd_comparison<'a, 'tcx>( } fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) -> Option> { - use crate::types::ExtremeType::*; + use crate::types::ExtremeType::{Maximum, Minimum}; let ty = cx.tables.expr_ty(expr); @@ -1755,8 +1759,8 @@ fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AbsurdExtremeComparisons { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { - use crate::types::AbsurdComparisonResult::*; - use crate::types::ExtremeType::*; + use crate::types::AbsurdComparisonResult::{AlwaysFalse, AlwaysTrue, InequalityImpossible}; + use crate::types::ExtremeType::{Maximum, Minimum}; if let ExprKind::Binary(ref cmp, ref lhs, ref rhs) = expr.kind { if let Some((culprit, result)) = detect_absurd_comparison(cx, cmp.node, lhs, rhs) { @@ -1863,7 +1867,7 @@ impl Ord for FullInt { } fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'_>) -> Option<(FullInt, FullInt)> { - use std::*; + use std::{i128, i16, i32, i64, i8, isize, u128, u16, u32, u64, u8, usize}; if let ExprKind::Cast(ref cast_exp, _) = expr.kind { let pre_cast_ty = cx.tables.expr_ty(cast_exp); @@ -1963,7 +1967,7 @@ fn upcast_comparison_bounds_err<'a, 'tcx>( rhs: &'tcx Expr<'_>, invert: bool, ) { - use crate::utils::comparisons::*; + use crate::utils::comparisons::Rel; if let Some((lb, ub)) = lhs_bounds { if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) { diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index eaf9f2e85cb6..355d2ec0f1c7 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -1,6 +1,6 @@ use crate::utils::{is_allowed, snippet, span_lint_and_sugg}; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{Expr, ExprKind, HirId}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 023096398756..2b2df4241505 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -3,7 +3,7 @@ use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::symbol::SymbolStr; -use syntax::ast::*; +use syntax::ast::{Ident, Item, ItemKind, UseTree, UseTreeKind}; declare_clippy_lint! { /// **What it does:** Checks for imports that remove "unsafe" from an item's diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 4fd421e4af94..79dd93e64ff8 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -2,8 +2,8 @@ use crate::utils::{higher::if_block, match_type, paths, span_lint_and_then, usag use if_chain::if_chain; use rustc::hir::map::Map; use rustc::lint::in_external_macro; -use rustc_hir::intravisit::*; -use rustc_hir::*; +use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; +use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Path, QPath, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index f1d66c1bc25c..4170dcc7fadf 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -7,7 +7,10 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_item, walk_path, walk_ty, NestedVisitorMap, Visitor}; -use rustc_hir::*; +use rustc_hir::{ + def, FnDecl, FnRetTy, FnSig, GenericArg, HirId, ImplItem, ImplItemKind, Item, ItemKind, Path, PathSegment, QPath, + TyKind, +}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::kw; diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 52ccdf95d57b..a4dc24cecc22 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -157,7 +157,7 @@ impl PrintVisitor { } fn next(&mut self, s: &'static str) -> String { - use std::collections::hash_map::Entry::*; + use std::collections::hash_map::Entry::{Occupied, Vacant}; match self.ids.entry(s) { // already there: start numbering from `1` Occupied(mut occ) => { diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index f5f35afa9baa..c62f95cd5624 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -3,7 +3,11 @@ use crate::utils::differing_macro_contexts; use rustc::ich::StableHashingContextProvider; use rustc::ty::TypeckTables; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_hir::*; +use rustc_hir::{ + BinOpKind, Block, BlockCheckMode, BodyId, BorrowKind, CaptureBy, Expr, ExprKind, Field, FnRetTy, GenericArg, + GenericArgs, Guard, Lifetime, LifetimeName, ParamName, Pat, PatKind, Path, PathSegment, QPath, Stmt, StmtKind, Ty, + TyKind, TypeBinding, +}; use rustc_lint::LateContext; use std::hash::Hash; use syntax::ast::Name; diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 759feafc75b7..85fee84cb3b9 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -9,7 +9,7 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use rustc_hir::*; +use rustc_hir::{Crate, Expr, ExprKind, HirId, Item, MutTy, Mutability, Path, Ty, TyKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::{Span, Spanned}; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index b13648afda9e..2689cab2817f 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -40,7 +40,10 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::intravisit::{NestedVisitorMap, Visitor}; use rustc_hir::Node; -use rustc_hir::*; +use rustc_hir::{ + def, Arm, Block, Body, Constness, Crate, Expr, ExprKind, FnDecl, HirId, ImplItem, ImplItemKind, Item, ItemKind, + MatchSource, Param, Pat, PatKind, Path, PathSegment, QPath, TraitItem, TraitItemKind, TraitRef, TyKind, Unsafety, +}; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::predicate_for_trait_def; use rustc_lint::{LateContext, Level, Lint, LintContext}; @@ -52,7 +55,7 @@ use smallvec::SmallVec; use syntax::ast::{self, Attribute, LitKind}; use crate::consts::{constant, Constant}; -use crate::reexport::*; +use crate::reexport::Name; /// Returns `true` if the two spans come from differing expansions (i.e., one is /// from a macro and one isn't). @@ -1289,7 +1292,7 @@ pub fn must_use_attr(attrs: &[Attribute]) -> Option<&Attribute> { // Returns whether the type has #[must_use] attribute pub fn is_must_use_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { - use ty::TyKind::*; + use ty::TyKind::{Adt, Array, Dynamic, Foreign, Opaque, RawPtr, Ref, Slice, Tuple}; match ty.kind { Adt(ref adt, _) => must_use_attr(&cx.tcx.get_attrs(adt.did)).is_some(), Foreign(ref did) => must_use_attr(&cx.tcx.get_attrs(*did)).is_some(), diff --git a/clippy_lints/src/utils/ptr.rs b/clippy_lints/src/utils/ptr.rs index 8a59bcc98549..3d97c18e9b4e 100644 --- a/clippy_lints/src/utils/ptr.rs +++ b/clippy_lints/src/utils/ptr.rs @@ -1,7 +1,7 @@ use crate::utils::{get_pat_name, match_var, snippet}; use rustc::hir::map::Map; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use rustc_hir::*; +use rustc_hir::{Body, BodyId, Expr, ExprKind, Param}; use rustc_lint::LateContext; use rustc_span::source_map::Span; use std::borrow::Cow; diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 5c9e3ab80bb5..278505859b72 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -426,7 +426,10 @@ enum Associativity { /// associative. #[must_use] fn associativity(op: &AssocOp) -> Associativity { - use syntax::util::parser::AssocOp::*; + use syntax::util::parser::AssocOp::{ + Add, As, Assign, AssignOp, BitAnd, BitOr, BitXor, Colon, Divide, DotDot, DotDotEq, Equal, Greater, + GreaterEqual, LAnd, LOr, Less, LessEqual, Modulus, Multiply, NotEqual, ShiftLeft, ShiftRight, Subtract, + }; match *op { Assign | AssignOp(_) => Associativity::Right, @@ -439,7 +442,7 @@ fn associativity(op: &AssocOp) -> Associativity { /// Converts a `hir::BinOp` to the corresponding assigning binary operator. fn hirbinop2assignop(op: hir::BinOp) -> AssocOp { - use syntax::token::BinOpToken::*; + use syntax::token::BinOpToken::{And, Caret, Minus, Or, Percent, Plus, Shl, Shr, Slash, Star}; AssocOp::AssignOp(match op.node { hir::BinOpKind::Add => Plus, @@ -466,7 +469,9 @@ fn hirbinop2assignop(op: hir::BinOp) -> AssocOp { /// Converts an `ast::BinOp` to the corresponding assigning binary operator. fn astbinop2assignop(op: ast::BinOp) -> AssocOp { - use syntax::ast::BinOpKind::*; + use syntax::ast::BinOpKind::{ + Add, And, BitAnd, BitOr, BitXor, Div, Eq, Ge, Gt, Le, Lt, Mul, Ne, Or, Rem, Shl, Shr, Sub, + }; use syntax::token::BinOpToken; AssocOp::AssignOp(match op.node { diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs index 8fff1c7a16cb..3e8b29295f39 100644 --- a/clippy_lints/src/utils/usage.rs +++ b/clippy_lints/src/utils/usage.rs @@ -4,11 +4,11 @@ use rustc::ty; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use rustc_hir::*; +use rustc_hir::{def_id, Expr, HirId, Path}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_span::symbol::Ident; -use rustc_typeck::expr_use_visitor::*; +use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase}; use syntax::ast; /// Returns a set of mutated local variable IDs, or `None` if mutations could not be determined. diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index bc2c827b0afd..726a34856aeb 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -3,7 +3,7 @@ use crate::utils::{higher, is_copy, snippet_with_applicability, span_lint_and_su use if_chain::if_chain; use rustc::ty::{self, Ty}; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{BorrowKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/wildcard_dependencies.rs b/clippy_lints/src/wildcard_dependencies.rs index 2aa68842da41..0be168d563ab 100644 --- a/clippy_lints/src/wildcard_dependencies.rs +++ b/clippy_lints/src/wildcard_dependencies.rs @@ -2,7 +2,7 @@ use crate::utils::span_lint; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::DUMMY_SP; -use syntax::ast::*; +use syntax::ast::Crate; use if_chain::if_chain; diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 0be52c2aa3d6..904e2fab07ad 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -9,7 +9,7 @@ use rustc_parse::parser; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::Symbol; use rustc_span::{BytePos, Span}; -use syntax::ast::*; +use syntax::ast::{Expr, ExprKind, Mac, StrLit, StrStyle}; use syntax::token; use syntax::tokenstream::TokenStream; @@ -317,7 +317,9 @@ fn newline_span(fmtstr: &StrLit) -> Span { /// ``` #[allow(clippy::too_many_lines)] fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (Option, Option) { - use fmt_macros::*; + use fmt_macros::{ + AlignUnknown, ArgumentImplicitlyIs, ArgumentIs, ArgumentNamed, CountImplied, FormatSpec, Parser, Piece, + }; let tts = tts.clone(); let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, None, false, false, None); diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index f36da58843f3..42cb9a77db02 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -1,7 +1,7 @@ use crate::consts::{constant_simple, Constant}; use crate::utils::span_lint_and_help; use if_chain::if_chain; -use rustc_hir::*; +use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/src/driver.rs b/src/driver.rs index 097b796e785b..7865f6bb9dd0 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -15,7 +15,7 @@ extern crate rustc_interface; use rustc::ty::TyCtxt; use rustc_interface::interface; -use rustc_tools_util::*; +use rustc_tools_util::VersionInfo; use lazy_static::lazy_static; use std::borrow::Cow; @@ -93,7 +93,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks { #[allow(clippy::find_map, clippy::filter_map)] fn describe_lints() { - use lintlist::*; + use lintlist::{Level, Lint, ALL_LINTS, LINT_LEVELS}; use std::collections::HashSet; println!( diff --git a/src/main.rs b/src/main.rs index 8f9afb95337d..93e6996be069 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ #![cfg_attr(feature = "deny-warnings", deny(warnings))] -use rustc_tools_util::*; +use rustc_tools_util::VersionInfo; const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code. From b562a519e69847d918d117dd9b729f92c7749d34 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 21 Feb 2020 09:40:13 +0100 Subject: [PATCH 124/243] Don't use use ty::TyKind::* --- clippy_lints/src/functions.rs | 11 +++++------ clippy_lints/src/utils/mod.rs | 16 +++++++++------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 26b9f2cd613f..620ec1f49510 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -497,18 +497,17 @@ fn is_mutable_pat(cx: &LateContext<'_, '_>, pat: &hir::Pat<'_>, tys: &mut FxHash static KNOWN_WRAPPER_TYS: &[&[&str]] = &[&["alloc", "rc", "Rc"], &["std", "sync", "Arc"]]; fn is_mutable_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, span: Span, tys: &mut FxHashSet) -> bool { - use ty::TyKind::{Adt, Array, Bool, Char, Float, Int, RawPtr, Ref, Slice, Str, Tuple, Uint}; match ty.kind { // primitive types are never mutable - Bool | Char | Int(_) | Uint(_) | Float(_) | Str => false, - Adt(ref adt, ref substs) => { + ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false, + ty::Adt(ref adt, ref substs) => { tys.insert(adt.did) && !ty.is_freeze(cx.tcx, cx.param_env, span) || KNOWN_WRAPPER_TYS.iter().any(|path| match_def_path(cx, adt.did, path)) && substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys)) }, - Tuple(ref substs) => substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys)), - Array(ty, _) | Slice(ty) => is_mutable_ty(cx, ty, span, tys), - RawPtr(ty::TypeAndMut { ty, mutbl }) | Ref(_, ty, mutbl) => { + ty::Tuple(ref substs) => substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys)), + ty::Array(ty, _) | ty::Slice(ty) => is_mutable_ty(cx, ty, span, tys), + ty::RawPtr(ty::TypeAndMut { ty, mutbl }) | ty::Ref(_, ty, mutbl) => { mutbl == hir::Mutability::Mut || is_mutable_ty(cx, ty, span, tys) }, // calling something constitutes a side effect, so return true on all callables diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 2689cab2817f..708e3feef293 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1292,17 +1292,19 @@ pub fn must_use_attr(attrs: &[Attribute]) -> Option<&Attribute> { // Returns whether the type has #[must_use] attribute pub fn is_must_use_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { - use ty::TyKind::{Adt, Array, Dynamic, Foreign, Opaque, RawPtr, Ref, Slice, Tuple}; match ty.kind { - Adt(ref adt, _) => must_use_attr(&cx.tcx.get_attrs(adt.did)).is_some(), - Foreign(ref did) => must_use_attr(&cx.tcx.get_attrs(*did)).is_some(), - Slice(ref ty) | Array(ref ty, _) | RawPtr(ty::TypeAndMut { ref ty, .. }) | Ref(_, ref ty, _) => { + ty::Adt(ref adt, _) => must_use_attr(&cx.tcx.get_attrs(adt.did)).is_some(), + ty::Foreign(ref did) => must_use_attr(&cx.tcx.get_attrs(*did)).is_some(), + ty::Slice(ref ty) + | ty::Array(ref ty, _) + | ty::RawPtr(ty::TypeAndMut { ref ty, .. }) + | ty::Ref(_, ref ty, _) => { // for the Array case we don't need to care for the len == 0 case // because we don't want to lint functions returning empty arrays is_must_use_ty(cx, *ty) }, - Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)), - Opaque(ref def_id, _) => { + ty::Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)), + ty::Opaque(ref def_id, _) => { for (predicate, _) in cx.tcx.predicates_of(*def_id).predicates { if let ty::Predicate::Trait(ref poly_trait_predicate, _) = predicate { if must_use_attr(&cx.tcx.get_attrs(poly_trait_predicate.skip_binder().trait_ref.def_id)).is_some() { @@ -1312,7 +1314,7 @@ pub fn is_must_use_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> boo } false }, - Dynamic(binder, _) => { + ty::Dynamic(binder, _) => { for predicate in binder.skip_binder().iter() { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate { if must_use_attr(&cx.tcx.get_attrs(trait_ref.def_id)).is_some() { From 4dd2252b17915a6b11b8e9ea4bc4500e80437a60 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 21 Feb 2020 10:15:38 +0100 Subject: [PATCH 125/243] Fix suggestion for weird formattings --- clippy_lints/src/wildcard_imports.rs | 26 ++++++++++++++++++++------ tests/ui/wildcard_imports.fixed | 9 +++++++++ tests/ui/wildcard_imports.rs | 10 ++++++++++ tests/ui/wildcard_imports.stderr | 16 +++++++++++++++- 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 3e8d28a22932..17e067a095de 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -1,4 +1,4 @@ -use crate::utils::{in_macro, snippet_with_applicability, span_lint_and_sugg}; +use crate::utils::{in_macro, snippet, snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{ @@ -46,6 +46,9 @@ declare_clippy_lint! { /// **Known problems:** If macros are imported through the wildcard, this macro is not included /// by the suggestion and has to be added by hand. /// + /// Applying the suggestion when explicit imports of the things imported with a glob import + /// exist, may result in `unused_imports` warnings. + /// /// **Example:** /// /// Bad: @@ -82,16 +85,27 @@ impl LateLintPass<'_, '_> for WildcardImports { if !used_imports.is_empty(); // Already handled by `unused_imports` then { let mut applicability = Applicability::MachineApplicable; - let import_source = snippet_with_applicability(cx, use_path.span, "..", &mut applicability); - let (span, braced_glob) = if import_source.is_empty() { + let import_source_snippet = snippet_with_applicability(cx, use_path.span, "..", &mut applicability); + let (span, braced_glob) = if import_source_snippet.is_empty() { // This is a `_::{_, *}` import + // In this case `use_path.span` is empty and ends directly in front of the `*`, + // so we need to extend it by one byte. ( use_path.span.with_hi(use_path.span.hi() + BytePos(1)), true, ) } else { + // In this case, the `use_path.span` ends right before the `::*`, so we need to + // extend it up to the `*`. Since it is hard to find the `*` in weird + // formattings like `use _ :: *;`, we extend it up to, but not including the + // `;`. In nested imports, like `use _::{inner::*, _}` there is no `;` and we + // can just use the end of the item span + let mut span = use_path.span.with_hi(item.span.hi()); + if snippet(cx, span, "").ends_with(';') { + span = use_path.span.with_hi(item.span.hi() - BytePos(1)); + } ( - use_path.span.with_hi(use_path.span.hi() + BytePos(3)), + span, false, ) }; @@ -111,10 +125,10 @@ impl LateLintPass<'_, '_> for WildcardImports { } }; - let sugg = if import_source.is_empty() { + let sugg = if braced_glob { imports_string } else { - format!("{}::{}", import_source, imports_string) + format!("{}::{}", import_source_snippet, imports_string) }; let (lint, message) = if let Res::Def(DefKind::Enum, _) = use_path.res { diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index 398c3b56572b..f447a92715dc 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -145,3 +145,12 @@ fn test_reexported() { let _ = ExportedStruct; let _ = ExportedEnum::A; } + +#[rustfmt::skip] +fn test_weird_formatting() { + use crate:: in_fn_test::exported; + use crate:: fn_mod::foo; + + exported(); + foo(); +} diff --git a/tests/ui/wildcard_imports.rs b/tests/ui/wildcard_imports.rs index 10ab25e02ade..3fd66763a9fc 100644 --- a/tests/ui/wildcard_imports.rs +++ b/tests/ui/wildcard_imports.rs @@ -145,3 +145,13 @@ fn test_reexported() { let _ = ExportedStruct; let _ = ExportedEnum::A; } + +#[rustfmt::skip] +fn test_weird_formatting() { + use crate:: in_fn_test:: * ; + use crate:: fn_mod:: + *; + + exported(); + foo(); +} diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr index ca300fbaad49..bebd9c1f8520 100644 --- a/tests/ui/wildcard_imports.stderr +++ b/tests/ui/wildcard_imports.stderr @@ -78,5 +78,19 @@ error: usage of wildcard import LL | use crate::in_fn_test::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` -error: aborting due to 13 previous errors +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:151:9 + | +LL | use crate:: in_fn_test:: * ; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:152:9 + | +LL | use crate:: fn_mod:: + | _________^ +LL | | *; + | |_________^ help: try: `crate:: fn_mod::foo` + +error: aborting due to 15 previous errors From 049079856bb300c9b00a1ddbf4b58d0a5ca40309 Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Fri, 21 Feb 2020 19:52:04 -0800 Subject: [PATCH 126/243] Prevent `missing_const_for_fn` on functions with const generic params `const` functions cannot have const generic parameters so prevent the `missing_const_for_fn` lint from firing in that case. --- clippy_lints/src/missing_const_for_fn.rs | 12 ++++++--- .../ui/missing_const_for_fn/cant_be_const.rs | 13 +++++++++- .../ui/missing_const_for_fn/could_be_const.rs | 7 ++++- .../could_be_const.stderr | 26 ++++++++++++------- 4 files changed, 44 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index dc5a58abe56d..e829baa22688 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -2,12 +2,13 @@ use crate::utils::{has_drop, is_entrypoint_fn, span_lint, trait_ref_of_method}; use rustc::lint::in_external_macro; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; -use rustc_hir::{Body, Constness, FnDecl, HirId}; +use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId}; use rustc_lint::{LateContext, LateLintPass}; use rustc_mir::transform::qualify_min_const_fn::is_min_const_fn; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::Span; use rustc_typeck::hir_ty_to_ty; +use std::matches; declare_clippy_lint! { /// **What it does:** @@ -90,8 +91,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn { // Perform some preliminary checks that rule out constness on the Clippy side. This way we // can skip the actual const check and return early. match kind { - FnKind::ItemFn(_, _, header, ..) => { - if already_const(header) { + FnKind::ItemFn(_, generics, header, ..) => { + let has_const_generic_params = generics + .params + .iter() + .any(|param| matches!(param.kind, GenericParamKind::Const{ .. })); + + if already_const(header) || has_const_generic_params { return; } }, diff --git a/tests/ui/missing_const_for_fn/cant_be_const.rs b/tests/ui/missing_const_for_fn/cant_be_const.rs index f367279906fd..ba352ef9ee93 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -3,7 +3,8 @@ //! The .stderr output of this test should be empty. Otherwise it's a bug somewhere. #![warn(clippy::missing_const_for_fn)] -#![feature(start)] +#![allow(incomplete_features)] +#![feature(start, const_generics)] struct Game; @@ -90,3 +91,13 @@ mod with_drop { } } } + +fn const_generic_params(t: &[T; N]) -> &[T; N] { + t +} + +fn const_generic_return(t: &[T]) -> &[T; N] { + let p = t.as_ptr() as *const [T; N]; + + unsafe { &*p } +} diff --git a/tests/ui/missing_const_for_fn/could_be_const.rs b/tests/ui/missing_const_for_fn/could_be_const.rs index 9a73dcbe99f1..c6f44b7daa34 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.rs +++ b/tests/ui/missing_const_for_fn/could_be_const.rs @@ -1,5 +1,6 @@ #![warn(clippy::missing_const_for_fn)] -#![allow(clippy::let_and_return)] +#![allow(incomplete_features, clippy::let_and_return)] +#![feature(const_generics)] use std::mem::transmute; @@ -12,6 +13,10 @@ impl Game { pub fn new() -> Self { Self { guess: 42 } } + + fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; N]) -> &'a [T; N] { + b + } } // Could be const diff --git a/tests/ui/missing_const_for_fn/could_be_const.stderr b/tests/ui/missing_const_for_fn/could_be_const.stderr index 165b8a030771..8dde56cd79f4 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.stderr +++ b/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -1,5 +1,5 @@ error: this could be a `const fn` - --> $DIR/could_be_const.rs:12:5 + --> $DIR/could_be_const.rs:13:5 | LL | / pub fn new() -> Self { LL | | Self { guess: 42 } @@ -9,7 +9,15 @@ LL | | } = note: `-D clippy::missing-const-for-fn` implied by `-D warnings` error: this could be a `const fn` - --> $DIR/could_be_const.rs:18:1 + --> $DIR/could_be_const.rs:17:5 + | +LL | / fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; N]) -> &'a [T; N] { +LL | | b +LL | | } + | |_____^ + +error: this could be a `const fn` + --> $DIR/could_be_const.rs:23:1 | LL | / fn one() -> i32 { LL | | 1 @@ -17,7 +25,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:23:1 + --> $DIR/could_be_const.rs:28:1 | LL | / fn two() -> i32 { LL | | let abc = 2; @@ -26,7 +34,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:29:1 + --> $DIR/could_be_const.rs:34:1 | LL | / fn string() -> String { LL | | String::new() @@ -34,7 +42,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:34:1 + --> $DIR/could_be_const.rs:39:1 | LL | / unsafe fn four() -> i32 { LL | | 4 @@ -42,7 +50,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:39:1 + --> $DIR/could_be_const.rs:44:1 | LL | / fn generic(t: T) -> T { LL | | t @@ -50,7 +58,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:43:1 + --> $DIR/could_be_const.rs:48:1 | LL | / fn sub(x: u32) -> usize { LL | | unsafe { transmute(&x) } @@ -58,12 +66,12 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:62:9 + --> $DIR/could_be_const.rs:67:9 | LL | / pub fn b(self, a: &A) -> B { LL | | B LL | | } | |_________^ -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors From 036ec5b63d4c507c6021c572a9102145b429fde5 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 24 Feb 2020 13:33:04 +0900 Subject: [PATCH 127/243] Rustup to rust-lang/rust#69366 --- clippy_lints/src/excessive_bools.rs | 4 ++-- clippy_lints/src/non_expressive_names.rs | 4 ++-- clippy_lints/src/redundant_static_lifetimes.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/excessive_bools.rs b/clippy_lints/src/excessive_bools.rs index aa91ab3bc774..71537d4a9f07 100644 --- a/clippy_lints/src/excessive_bools.rs +++ b/clippy_lints/src/excessive_bools.rs @@ -162,12 +162,12 @@ impl EarlyLintPass for ExcessiveBools { } | ItemKind::Trait(_, _, _, _, items) => { for item in items { - if let AssocItemKind::Fn(fn_sig, _, _) = &item.kind { + if let AssocItemKind::Fn(_, fn_sig, _, _) = &item.kind { self.check_fn_sig(cx, fn_sig, item.span); } } }, - ItemKind::Fn(fn_sig, _, _) => self.check_fn_sig(cx, fn_sig, item.span), + ItemKind::Fn(_, fn_sig, _, _) => self.check_fn_sig(cx, fn_sig, item.span), _ => (), } } diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index de5ae5d30322..cb3e9ccba1e4 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -354,13 +354,13 @@ impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> { impl EarlyLintPass for NonExpressiveNames { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if let ItemKind::Fn(ref sig, _, Some(ref blk)) = item.kind { + if let ItemKind::Fn(_, ref sig, _, Some(ref blk)) = item.kind { do_check(self, cx, &item.attrs, &sig.decl, blk); } } fn check_impl_item(&mut self, cx: &EarlyContext<'_>, item: &AssocItem) { - if let AssocItemKind::Fn(ref sig, _, Some(ref blk)) = item.kind { + if let AssocItemKind::Fn(_, ref sig, _, Some(ref blk)) = item.kind { do_check(self, cx, &item.attrs, &sig.decl, blk); } } diff --git a/clippy_lints/src/redundant_static_lifetimes.rs b/clippy_lints/src/redundant_static_lifetimes.rs index 98ec793de7c1..feb045f9c152 100644 --- a/clippy_lints/src/redundant_static_lifetimes.rs +++ b/clippy_lints/src/redundant_static_lifetimes.rs @@ -79,7 +79,7 @@ impl RedundantStaticLifetimes { impl EarlyLintPass for RedundantStaticLifetimes { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { if !item.span.from_expansion() { - if let ItemKind::Const(ref var_type, _) = item.kind { + if let ItemKind::Const(_, ref var_type, _) = item.kind { self.visit_type(var_type, cx, "Constants have by default a `'static` lifetime"); // Don't check associated consts because `'static` cannot be elided on those (issue // #2438) From ee91b5b2ddf00480dc43b9bab94a5a27ef369704 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 24 Feb 2020 13:38:35 +0900 Subject: [PATCH 128/243] Do not run deploy action on other repos --- .github/workflows/deploy.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index be40b27440d7..5b7bec81999a 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -15,6 +15,7 @@ env: jobs: deploy: runs-on: ubuntu-latest + if: github.repository == 'rust-lang/rust-clippy' steps: # Setup From c636c6a55b92daef5af4e1c459c0eaf3f5787945 Mon Sep 17 00:00:00 2001 From: Krishna Veera Reddy Date: Sat, 14 Dec 2019 09:28:11 -0800 Subject: [PATCH 129/243] Add lints to detect inaccurate and inefficient FP operations Add lints to detect floating point computations that are either inaccurate or inefficient and suggest better alternatives. --- CHANGELOG.md | 1 + clippy_lints/src/floating_point_arithmetic.rs | 228 ++++++++++++++++++ clippy_lints/src/lib.rs | 3 + src/lintlist/mod.rs | 7 + tests/ui/floating_point_arithmetic.rs | 76 ++++++ tests/ui/floating_point_arithmetic.stderr | 174 +++++++++++++ 6 files changed, 489 insertions(+) create mode 100644 clippy_lints/src/floating_point_arithmetic.rs create mode 100644 tests/ui/floating_point_arithmetic.rs create mode 100644 tests/ui/floating_point_arithmetic.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e99342e4a42..55e46bf6d20e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1169,6 +1169,7 @@ Released 2018-09-13 [`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond [`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher [`implicit_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return +[`inaccurate_floating_point_computation`]: https://rust-lang.github.io/rust-clippy/master/index.html#inaccurate_floating_point_computation [`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping [`indexing_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing [`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs new file mode 100644 index 000000000000..935d8b581466 --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -0,0 +1,228 @@ +use crate::consts::{ + constant, + Constant::{F32, F64}, +}; +use crate::utils::*; +use if_chain::if_chain; +use rustc::declare_lint_pass; +use rustc::hir::*; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc_errors::Applicability; +use rustc_session::declare_tool_lint; +use std::f32::consts as f32_consts; +use std::f64::consts as f64_consts; + +declare_clippy_lint! { + /// **What it does:** Looks for numerically unstable floating point + /// computations and suggests better alternatives. + /// + /// **Why is this bad?** Numerically unstable floating point computations + /// cause rounding errors to magnify and distorts the results strongly. + /// + /// **Known problems:** None + /// + /// **Example:** + /// + /// ```rust + /// use std::f32::consts::E; + /// + /// let a = 1f32.log(2.0); + /// let b = 1f32.log(10.0); + /// let c = 1f32.log(E); + /// ``` + /// + /// is better expressed as + /// + /// ```rust + /// let a = 1f32.log2(); + /// let b = 1f32.log10(); + /// let c = 1f32.ln(); + /// ``` + pub INACCURATE_FLOATING_POINT_COMPUTATION, + nursery, + "checks for numerically unstable floating point computations" +} + +declare_clippy_lint! { + /// **What it does:** Looks for inefficient floating point computations + /// and suggests faster alternatives. + /// + /// **Why is this bad?** Lower performance. + /// + /// **Known problems:** None + /// + /// **Example:** + /// + /// ```rust + /// use std::f32::consts::E; + /// + /// let a = (2f32).powf(3.0); + /// let c = E.powf(3.0); + /// ``` + /// + /// is better expressed as + /// + /// ```rust + /// let a = (3f32).exp2(); + /// let b = (3f32).exp(); + /// ``` + pub SLOW_FLOATING_POINT_COMPUTATION, + nursery, + "checks for inefficient floating point computations" +} + +declare_lint_pass!(FloatingPointArithmetic => [ + INACCURATE_FLOATING_POINT_COMPUTATION, + SLOW_FLOATING_POINT_COMPUTATION +]); + +fn check_log_base(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { + let recv = &args[0]; + let arg = sugg::Sugg::hir(cx, recv, "..").maybe_par(); + + if let Some((value, _)) = constant(cx, cx.tables, &args[1]) { + let method; + + if F32(2.0) == value || F64(2.0) == value { + method = "log2"; + } else if F32(10.0) == value || F64(10.0) == value { + method = "log10"; + } else if F32(f32_consts::E) == value || F64(f64_consts::E) == value { + method = "ln"; + } else { + return; + } + + span_lint_and_sugg( + cx, + INACCURATE_FLOATING_POINT_COMPUTATION, + expr.span, + "logarithm for bases 2, 10 and e can be computed more accurately", + "consider using", + format!("{}.{}()", arg, method), + Applicability::MachineApplicable, + ); + } +} + +// TODO: Lint expressions of the form `(x + 1).ln()` and `(x + y).ln()` +// where y > 1 and suggest usage of `(x + (y - 1)).ln_1p()` instead +fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { + if_chain! { + if let ExprKind::Binary(op, ref lhs, ref rhs) = &args[0].kind; + if op.node == BinOpKind::Add; + if let Some((value, _)) = constant(cx, cx.tables, lhs); + if F32(1.0) == value || F64(1.0) == value; + then { + let arg = sugg::Sugg::hir(cx, rhs, "..").maybe_par(); + + span_lint_and_sugg( + cx, + INACCURATE_FLOATING_POINT_COMPUTATION, + expr.span, + "ln(1 + x) can be computed more accurately", + "consider using", + format!("{}.ln_1p()", arg), + Applicability::MachineApplicable, + ); + } + } +} + +fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { + // Check receiver + if let Some((value, _)) = constant(cx, cx.tables, &args[0]) { + let method; + + if F32(f32_consts::E) == value || F64(f64_consts::E) == value { + method = "exp"; + } else if F32(2.0) == value || F64(2.0) == value { + method = "exp2"; + } else { + return; + } + + span_lint_and_sugg( + cx, + SLOW_FLOATING_POINT_COMPUTATION, + expr.span, + "exponent for bases 2 and e can be computed more efficiently", + "consider using", + format!("{}.{}()", sugg::Sugg::hir(cx, &args[1], "..").maybe_par(), method), + Applicability::MachineApplicable, + ); + } + + // Check argument + if let Some((value, _)) = constant(cx, cx.tables, &args[1]) { + let help; + let method; + + if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value { + help = "square-root of a number can be computer more efficiently"; + method = "sqrt"; + } else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value { + help = "cube-root of a number can be computer more efficiently"; + method = "cbrt"; + } else { + return; + } + + span_lint_and_sugg( + cx, + SLOW_FLOATING_POINT_COMPUTATION, + expr.span, + help, + "consider using", + format!("{}.{}()", sugg::Sugg::hir(cx, &args[0], ".."), method), + Applicability::MachineApplicable, + ); + } +} + +// TODO: Lint expressions of the form `x.exp() - y` where y > 1 +// and suggest usage of `x.exp_m1() - (y - 1)` instead +fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr) { + if_chain! { + if let ExprKind::Binary(op, ref lhs, ref rhs) = expr.kind; + if op.node == BinOpKind::Sub; + if cx.tables.expr_ty(lhs).is_floating_point(); + if let Some((value, _)) = constant(cx, cx.tables, rhs); + if F32(1.0) == value || F64(1.0) == value; + if let ExprKind::MethodCall(ref path, _, ref method_args) = lhs.kind; + if path.ident.name.as_str() == "exp"; + then { + span_lint_and_sugg( + cx, + INACCURATE_FLOATING_POINT_COMPUTATION, + expr.span, + "(e.pow(x) - 1) can be computed more accurately", + "consider using", + format!( + "{}.exp_m1()", + sugg::Sugg::hir(cx, &method_args[0], "..") + ), + Applicability::MachineApplicable, + ); + } + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if let ExprKind::MethodCall(ref path, _, args) = &expr.kind { + let recv_ty = cx.tables.expr_ty(&args[0]); + + if recv_ty.is_floating_point() { + match &*path.ident.name.as_str() { + "ln" => check_ln1p(cx, expr, args), + "log" => check_log_base(cx, expr, args), + "powf" => check_powf(cx, expr, args), + _ => {}, + } + } + } else { + check_expm1(cx, expr); + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 2b5691f92555..9a904141fcf4 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1000,6 +1000,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box to_digit_is_some::ToDigitIsSome); let array_size_threshold = conf.array_size_threshold; store.register_late_pass(move || box large_stack_arrays::LargeStackArrays::new(array_size_threshold)); + store.register_late_pass(move || box floating_point_arithmetic::FloatingPointArithmetic); store.register_early_pass(|| box as_conversions::AsConversions); store.register_early_pass(|| box utils::internal_lints::ProduceIce); store.register_late_pass(|| box let_underscore::LetUnderscore); @@ -1648,6 +1649,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![ LintId::of(&attrs::EMPTY_LINE_AFTER_OUTER_ATTR), LintId::of(&fallible_impl_from::FALLIBLE_IMPL_FROM), + LintId::of(&floating_point_arithmetic::INACCURATE_FLOATING_POINT_COMPUTATION), + LintId::of(&floating_point_arithmetic::SLOW_FLOATING_POINT_COMPUTATION), LintId::of(&missing_const_for_fn::MISSING_CONST_FOR_FN), LintId::of(&mul_add::MANUAL_MUL_ADD), LintId::of(&mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 29b5a7ba08a2..fee595074547 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -749,6 +749,13 @@ pub const ALL_LINTS: [Lint; 357] = [ deprecation: None, module: "implicit_return", }, + Lint { + name: "inaccurate_floating_point_computation", + group: "nursery", + desc: "checks for numerically unstable floating point computations", + deprecation: None, + module: "floating_point_arithmetic", + }, Lint { name: "inconsistent_digit_grouping", group: "style", diff --git a/tests/ui/floating_point_arithmetic.rs b/tests/ui/floating_point_arithmetic.rs new file mode 100644 index 000000000000..5291e5cf0226 --- /dev/null +++ b/tests/ui/floating_point_arithmetic.rs @@ -0,0 +1,76 @@ +#![allow(dead_code)] +#![warn( + clippy::inaccurate_floating_point_computation, + clippy::slow_floating_point_computation +)] + +const TWO: f32 = 2.0; +const E: f32 = std::f32::consts::E; + +fn check_log_base() { + let x = 1f32; + let _ = x.log(2f32); + let _ = x.log(10f32); + let _ = x.log(std::f32::consts::E); + let _ = x.log(TWO); + let _ = x.log(E); + + let x = 1f64; + let _ = x.log(2f64); + let _ = x.log(10f64); + let _ = x.log(std::f64::consts::E); +} + +fn check_ln1p() { + let x = 1f32; + let _ = (1.0 + x).ln(); + let _ = (1.0 + x * 2.0).ln(); + let _ = (1.0 + x.powi(2)).ln(); + let _ = (1.0 + x.powi(2) * 2.0).ln(); + let _ = (1.0 + (std::f32::consts::E - 1.0)).ln(); + // Cases where the lint shouldn't be applied + let _ = (x + 1.0).ln(); + let _ = (1.0 + x + 2.0).ln(); + let _ = (1.0 + x - 2.0).ln(); + + let x = 1f64; + let _ = (1.0 + x).ln(); + let _ = (1.0 + x * 2.0).ln(); + let _ = (1.0 + x.powi(2)).ln(); + // Cases where the lint shouldn't be applied + let _ = (x + 1.0).ln(); + let _ = (1.0 + x + 2.0).ln(); + let _ = (1.0 + x - 2.0).ln(); +} + +fn check_powf() { + let x = 3f32; + let _ = 2f32.powf(x); + let _ = std::f32::consts::E.powf(x); + let _ = x.powf(1.0 / 2.0); + let _ = x.powf(1.0 / 3.0); + + let x = 3f64; + let _ = 2f64.powf(x); + let _ = std::f64::consts::E.powf(x); + let _ = x.powf(1.0 / 2.0); + let _ = x.powf(1.0 / 3.0); +} + +fn check_expm1() { + let x = 2f32; + let _ = x.exp() - 1.0; + let _ = x.exp() - 1.0 + 2.0; + // Cases where the lint shouldn't be applied + let _ = x.exp() - 2.0; + let _ = x.exp() - 1.0 * 2.0; + + let x = 2f64; + let _ = x.exp() - 1.0; + let _ = x.exp() - 1.0 + 2.0; + // Cases where the lint shouldn't be applied + let _ = x.exp() - 2.0; + let _ = x.exp() - 1.0 * 2.0; +} + +fn main() {} diff --git a/tests/ui/floating_point_arithmetic.stderr b/tests/ui/floating_point_arithmetic.stderr new file mode 100644 index 000000000000..a0663e488354 --- /dev/null +++ b/tests/ui/floating_point_arithmetic.stderr @@ -0,0 +1,174 @@ +error: logarithm for bases 2, 10 and e can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:12:13 + | +LL | let _ = x.log(2f32); + | ^^^^^^^^^^^ help: consider using: `x.log2()` + | + = note: `-D clippy::inaccurate-floating-point-computation` implied by `-D warnings` + +error: logarithm for bases 2, 10 and e can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:13:13 + | +LL | let _ = x.log(10f32); + | ^^^^^^^^^^^^ help: consider using: `x.log10()` + +error: logarithm for bases 2, 10 and e can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:14:13 + | +LL | let _ = x.log(std::f32::consts::E); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.ln()` + +error: logarithm for bases 2, 10 and e can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:15:13 + | +LL | let _ = x.log(TWO); + | ^^^^^^^^^^ help: consider using: `x.log2()` + +error: logarithm for bases 2, 10 and e can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:16:13 + | +LL | let _ = x.log(E); + | ^^^^^^^^ help: consider using: `x.ln()` + +error: logarithm for bases 2, 10 and e can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:19:13 + | +LL | let _ = x.log(2f64); + | ^^^^^^^^^^^ help: consider using: `x.log2()` + +error: logarithm for bases 2, 10 and e can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:20:13 + | +LL | let _ = x.log(10f64); + | ^^^^^^^^^^^^ help: consider using: `x.log10()` + +error: logarithm for bases 2, 10 and e can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:21:13 + | +LL | let _ = x.log(std::f64::consts::E); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.ln()` + +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:26:13 + | +LL | let _ = (1.0 + x).ln(); + | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:27:13 + | +LL | let _ = (1.0 + x * 2.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:28:13 + | +LL | let _ = (1.0 + x.powi(2)).ln(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:29:13 + | +LL | let _ = (1.0 + x.powi(2) * 2.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x.powi(2) * 2.0).ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:30:13 + | +LL | let _ = (1.0 + (std::f32::consts::E - 1.0)).ln(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `((std::f32::consts::E - 1.0)).ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:37:13 + | +LL | let _ = (1.0 + x).ln(); + | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:38:13 + | +LL | let _ = (1.0 + x * 2.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:39:13 + | +LL | let _ = (1.0 + x.powi(2)).ln(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` + +error: exponent for bases 2 and e can be computed more efficiently + --> $DIR/floating_point_arithmetic.rs:48:13 + | +LL | let _ = 2f32.powf(x); + | ^^^^^^^^^^^^ help: consider using: `x.exp2()` + | + = note: `-D clippy::slow-floating-point-computation` implied by `-D warnings` + +error: exponent for bases 2 and e can be computed more efficiently + --> $DIR/floating_point_arithmetic.rs:49:13 + | +LL | let _ = std::f32::consts::E.powf(x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()` + +error: square-root of a number can be computer more efficiently + --> $DIR/floating_point_arithmetic.rs:50:13 + | +LL | let _ = x.powf(1.0 / 2.0); + | ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()` + +error: cube-root of a number can be computer more efficiently + --> $DIR/floating_point_arithmetic.rs:51:13 + | +LL | let _ = x.powf(1.0 / 3.0); + | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` + +error: exponent for bases 2 and e can be computed more efficiently + --> $DIR/floating_point_arithmetic.rs:54:13 + | +LL | let _ = 2f64.powf(x); + | ^^^^^^^^^^^^ help: consider using: `x.exp2()` + +error: exponent for bases 2 and e can be computed more efficiently + --> $DIR/floating_point_arithmetic.rs:55:13 + | +LL | let _ = std::f64::consts::E.powf(x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()` + +error: square-root of a number can be computer more efficiently + --> $DIR/floating_point_arithmetic.rs:56:13 + | +LL | let _ = x.powf(1.0 / 2.0); + | ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()` + +error: cube-root of a number can be computer more efficiently + --> $DIR/floating_point_arithmetic.rs:57:13 + | +LL | let _ = x.powf(1.0 / 3.0); + | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` + +error: (e.pow(x) - 1) can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:62:13 + | +LL | let _ = x.exp() - 1.0; + | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` + +error: (e.pow(x) - 1) can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:63:13 + | +LL | let _ = x.exp() - 1.0 + 2.0; + | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` + +error: (e.pow(x) - 1) can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:69:13 + | +LL | let _ = x.exp() - 1.0; + | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` + +error: (e.pow(x) - 1) can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:70:13 + | +LL | let _ = x.exp() - 1.0 + 2.0; + | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` + +error: aborting due to 28 previous errors + From 1f4f357bf540f63ece5d11d5ab6cae9a8fb63a21 Mon Sep 17 00:00:00 2001 From: Krishna Veera Reddy Date: Sat, 14 Dec 2019 20:10:23 -0800 Subject: [PATCH 130/243] Consolidate the accuracy and efficiency lints Merge the accuracy and efficiency lints into a single lint that checks for improvements to accuracy, efficiency and readability of floating-point expressions. --- CHANGELOG.md | 1 - clippy_lints/src/floating_point_arithmetic.rs | 89 ++++++++----------- clippy_lints/src/lib.rs | 3 +- src/lintlist/mod.rs | 7 -- tests/ui/floating_point_arithmetic.rs | 5 +- tests/ui/floating_point_arithmetic.stderr | 76 ++++++++-------- 6 files changed, 76 insertions(+), 105 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55e46bf6d20e..4e99342e4a42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1169,7 +1169,6 @@ Released 2018-09-13 [`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond [`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher [`implicit_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return -[`inaccurate_floating_point_computation`]: https://rust-lang.github.io/rust-clippy/master/index.html#inaccurate_floating_point_computation [`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping [`indexing_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing [`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 935d8b581466..da55f1e5f4e3 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -13,11 +13,12 @@ use std::f32::consts as f32_consts; use std::f64::consts as f64_consts; declare_clippy_lint! { - /// **What it does:** Looks for numerically unstable floating point - /// computations and suggests better alternatives. + /// **What it does:** Looks for floating-point expressions that + /// can be expressed using built-in methods to improve accuracy, + /// performance and/or succinctness. /// - /// **Why is this bad?** Numerically unstable floating point computations - /// cause rounding errors to magnify and distorts the results strongly. + /// **Why is this bad?** Negatively affects accuracy, performance + /// and/or readability. /// /// **Known problems:** None /// @@ -26,59 +27,43 @@ declare_clippy_lint! { /// ```rust /// use std::f32::consts::E; /// - /// let a = 1f32.log(2.0); - /// let b = 1f32.log(10.0); - /// let c = 1f32.log(E); + /// let a = 3f32; + /// let _ = (2f32).powf(a); + /// let _ = E.powf(a); + /// let _ = a.powf(1.0 / 2.0); + /// let _ = a.powf(1.0 / 3.0); + /// let _ = a.log(2.0); + /// let _ = a.log(10.0); + /// let _ = a.log(E); + /// let _ = (1.0 + a).ln(); + /// let _ = a.exp() - 1.0; /// ``` /// /// is better expressed as /// /// ```rust - /// let a = 1f32.log2(); - /// let b = 1f32.log10(); - /// let c = 1f32.ln(); - /// ``` - pub INACCURATE_FLOATING_POINT_COMPUTATION, - nursery, - "checks for numerically unstable floating point computations" -} - -declare_clippy_lint! { - /// **What it does:** Looks for inefficient floating point computations - /// and suggests faster alternatives. - /// - /// **Why is this bad?** Lower performance. - /// - /// **Known problems:** None - /// - /// **Example:** - /// - /// ```rust /// use std::f32::consts::E; /// - /// let a = (2f32).powf(3.0); - /// let c = E.powf(3.0); - /// ``` - /// - /// is better expressed as - /// - /// ```rust - /// let a = (3f32).exp2(); - /// let b = (3f32).exp(); + /// let a = 3f32; + /// let _ = a.exp2(); + /// let _ = a.exp(); + /// let _ = a.sqrt(); + /// let _ = a.cbrt(); + /// let _ = a.log2(); + /// let _ = a.log10(); + /// let _ = a.ln(); + /// let _ = a.ln_1p(); + /// let _ = a.exp_m1(); /// ``` - pub SLOW_FLOATING_POINT_COMPUTATION, + pub FLOATING_POINT_IMPROVEMENTS, nursery, - "checks for inefficient floating point computations" + "looks for improvements to floating-point expressions" } -declare_lint_pass!(FloatingPointArithmetic => [ - INACCURATE_FLOATING_POINT_COMPUTATION, - SLOW_FLOATING_POINT_COMPUTATION -]); +declare_lint_pass!(FloatingPointArithmetic => [FLOATING_POINT_IMPROVEMENTS]); fn check_log_base(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { - let recv = &args[0]; - let arg = sugg::Sugg::hir(cx, recv, "..").maybe_par(); + let arg = sugg::Sugg::hir(cx, &args[0], "..").maybe_par(); if let Some((value, _)) = constant(cx, cx.tables, &args[1]) { let method; @@ -95,7 +80,7 @@ fn check_log_base(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { span_lint_and_sugg( cx, - INACCURATE_FLOATING_POINT_COMPUTATION, + FLOATING_POINT_IMPROVEMENTS, expr.span, "logarithm for bases 2, 10 and e can be computed more accurately", "consider using", @@ -118,7 +103,7 @@ fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { span_lint_and_sugg( cx, - INACCURATE_FLOATING_POINT_COMPUTATION, + FLOATING_POINT_IMPROVEMENTS, expr.span, "ln(1 + x) can be computed more accurately", "consider using", @@ -144,9 +129,9 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { span_lint_and_sugg( cx, - SLOW_FLOATING_POINT_COMPUTATION, + FLOATING_POINT_IMPROVEMENTS, expr.span, - "exponent for bases 2 and e can be computed more efficiently", + "exponent for bases 2 and e can be computed more accurately", "consider using", format!("{}.{}()", sugg::Sugg::hir(cx, &args[1], "..").maybe_par(), method), Applicability::MachineApplicable, @@ -159,10 +144,10 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { let method; if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value { - help = "square-root of a number can be computer more efficiently"; + help = "square-root of a number can be computed more efficiently and accurately"; method = "sqrt"; } else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value { - help = "cube-root of a number can be computer more efficiently"; + help = "cube-root of a number can be computed more accurately"; method = "cbrt"; } else { return; @@ -170,7 +155,7 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { span_lint_and_sugg( cx, - SLOW_FLOATING_POINT_COMPUTATION, + FLOATING_POINT_IMPROVEMENTS, expr.span, help, "consider using", @@ -194,7 +179,7 @@ fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr) { then { span_lint_and_sugg( cx, - INACCURATE_FLOATING_POINT_COMPUTATION, + FLOATING_POINT_IMPROVEMENTS, expr.span, "(e.pow(x) - 1) can be computed more accurately", "consider using", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9a904141fcf4..9154a0dc3fff 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1649,8 +1649,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![ LintId::of(&attrs::EMPTY_LINE_AFTER_OUTER_ATTR), LintId::of(&fallible_impl_from::FALLIBLE_IMPL_FROM), - LintId::of(&floating_point_arithmetic::INACCURATE_FLOATING_POINT_COMPUTATION), - LintId::of(&floating_point_arithmetic::SLOW_FLOATING_POINT_COMPUTATION), + LintId::of(&floating_point_arithmetic::FLOATING_POINT_IMPROVEMENTS), LintId::of(&missing_const_for_fn::MISSING_CONST_FOR_FN), LintId::of(&mul_add::MANUAL_MUL_ADD), LintId::of(&mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index fee595074547..29b5a7ba08a2 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -749,13 +749,6 @@ pub const ALL_LINTS: [Lint; 357] = [ deprecation: None, module: "implicit_return", }, - Lint { - name: "inaccurate_floating_point_computation", - group: "nursery", - desc: "checks for numerically unstable floating point computations", - deprecation: None, - module: "floating_point_arithmetic", - }, Lint { name: "inconsistent_digit_grouping", group: "style", diff --git a/tests/ui/floating_point_arithmetic.rs b/tests/ui/floating_point_arithmetic.rs index 5291e5cf0226..1feeb827621a 100644 --- a/tests/ui/floating_point_arithmetic.rs +++ b/tests/ui/floating_point_arithmetic.rs @@ -1,8 +1,5 @@ #![allow(dead_code)] -#![warn( - clippy::inaccurate_floating_point_computation, - clippy::slow_floating_point_computation -)] +#![warn(clippy::floating_point_improvements)] const TWO: f32 = 2.0; const E: f32 = std::f32::consts::E; diff --git a/tests/ui/floating_point_arithmetic.stderr b/tests/ui/floating_point_arithmetic.stderr index a0663e488354..a7db1669745a 100644 --- a/tests/ui/floating_point_arithmetic.stderr +++ b/tests/ui/floating_point_arithmetic.stderr @@ -1,171 +1,169 @@ error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:12:13 + --> $DIR/floating_point_arithmetic.rs:9:13 | LL | let _ = x.log(2f32); | ^^^^^^^^^^^ help: consider using: `x.log2()` | - = note: `-D clippy::inaccurate-floating-point-computation` implied by `-D warnings` + = note: `-D clippy::floating-point-improvements` implied by `-D warnings` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:13:13 + --> $DIR/floating_point_arithmetic.rs:10:13 | LL | let _ = x.log(10f32); | ^^^^^^^^^^^^ help: consider using: `x.log10()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:14:13 + --> $DIR/floating_point_arithmetic.rs:11:13 | LL | let _ = x.log(std::f32::consts::E); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.ln()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:15:13 + --> $DIR/floating_point_arithmetic.rs:12:13 | LL | let _ = x.log(TWO); | ^^^^^^^^^^ help: consider using: `x.log2()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:16:13 + --> $DIR/floating_point_arithmetic.rs:13:13 | LL | let _ = x.log(E); | ^^^^^^^^ help: consider using: `x.ln()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:19:13 + --> $DIR/floating_point_arithmetic.rs:16:13 | LL | let _ = x.log(2f64); | ^^^^^^^^^^^ help: consider using: `x.log2()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:20:13 + --> $DIR/floating_point_arithmetic.rs:17:13 | LL | let _ = x.log(10f64); | ^^^^^^^^^^^^ help: consider using: `x.log10()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:21:13 + --> $DIR/floating_point_arithmetic.rs:18:13 | LL | let _ = x.log(std::f64::consts::E); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.ln()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:26:13 + --> $DIR/floating_point_arithmetic.rs:23:13 | LL | let _ = (1.0 + x).ln(); | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:27:13 + --> $DIR/floating_point_arithmetic.rs:24:13 | LL | let _ = (1.0 + x * 2.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:28:13 + --> $DIR/floating_point_arithmetic.rs:25:13 | LL | let _ = (1.0 + x.powi(2)).ln(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:29:13 + --> $DIR/floating_point_arithmetic.rs:26:13 | LL | let _ = (1.0 + x.powi(2) * 2.0).ln(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x.powi(2) * 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:30:13 + --> $DIR/floating_point_arithmetic.rs:27:13 | LL | let _ = (1.0 + (std::f32::consts::E - 1.0)).ln(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `((std::f32::consts::E - 1.0)).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:37:13 + --> $DIR/floating_point_arithmetic.rs:34:13 | LL | let _ = (1.0 + x).ln(); | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:38:13 + --> $DIR/floating_point_arithmetic.rs:35:13 | LL | let _ = (1.0 + x * 2.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:39:13 + --> $DIR/floating_point_arithmetic.rs:36:13 | LL | let _ = (1.0 + x.powi(2)).ln(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` -error: exponent for bases 2 and e can be computed more efficiently - --> $DIR/floating_point_arithmetic.rs:48:13 +error: exponent for bases 2 and e can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:45:13 | LL | let _ = 2f32.powf(x); | ^^^^^^^^^^^^ help: consider using: `x.exp2()` - | - = note: `-D clippy::slow-floating-point-computation` implied by `-D warnings` -error: exponent for bases 2 and e can be computed more efficiently - --> $DIR/floating_point_arithmetic.rs:49:13 +error: exponent for bases 2 and e can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:46:13 | LL | let _ = std::f32::consts::E.powf(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()` -error: square-root of a number can be computer more efficiently - --> $DIR/floating_point_arithmetic.rs:50:13 +error: square-root of a number can be computed more efficiently and accurately + --> $DIR/floating_point_arithmetic.rs:47:13 | LL | let _ = x.powf(1.0 / 2.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()` -error: cube-root of a number can be computer more efficiently - --> $DIR/floating_point_arithmetic.rs:51:13 +error: cube-root of a number can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:48:13 | LL | let _ = x.powf(1.0 / 3.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` -error: exponent for bases 2 and e can be computed more efficiently - --> $DIR/floating_point_arithmetic.rs:54:13 +error: exponent for bases 2 and e can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:51:13 | LL | let _ = 2f64.powf(x); | ^^^^^^^^^^^^ help: consider using: `x.exp2()` -error: exponent for bases 2 and e can be computed more efficiently - --> $DIR/floating_point_arithmetic.rs:55:13 +error: exponent for bases 2 and e can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:52:13 | LL | let _ = std::f64::consts::E.powf(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()` -error: square-root of a number can be computer more efficiently - --> $DIR/floating_point_arithmetic.rs:56:13 +error: square-root of a number can be computed more efficiently and accurately + --> $DIR/floating_point_arithmetic.rs:53:13 | LL | let _ = x.powf(1.0 / 2.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()` -error: cube-root of a number can be computer more efficiently - --> $DIR/floating_point_arithmetic.rs:57:13 +error: cube-root of a number can be computed more accurately + --> $DIR/floating_point_arithmetic.rs:54:13 | LL | let _ = x.powf(1.0 / 3.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` error: (e.pow(x) - 1) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:62:13 + --> $DIR/floating_point_arithmetic.rs:59:13 | LL | let _ = x.exp() - 1.0; | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` error: (e.pow(x) - 1) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:63:13 + --> $DIR/floating_point_arithmetic.rs:60:13 | LL | let _ = x.exp() - 1.0 + 2.0; | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` error: (e.pow(x) - 1) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:69:13 + --> $DIR/floating_point_arithmetic.rs:66:13 | LL | let _ = x.exp() - 1.0; | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` error: (e.pow(x) - 1) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:70:13 + --> $DIR/floating_point_arithmetic.rs:67:13 | LL | let _ = x.exp() - 1.0 + 2.0; | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` From 9520d3dfa4d3213ef07894dd99d201aeab255fa3 Mon Sep 17 00:00:00 2001 From: Krishna Veera Reddy Date: Sun, 15 Dec 2019 19:26:44 -0800 Subject: [PATCH 131/243] Suggest usage of `powi` method when applicable --- clippy_lints/src/floating_point_arithmetic.rs | 41 +++++++++++++++++- tests/ui/floating_point_arithmetic.rs | 12 ++++++ tests/ui/floating_point_arithmetic.stderr | 42 +++++++++++++++---- 3 files changed, 85 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index da55f1e5f4e3..84a9cac5b634 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -1,5 +1,5 @@ use crate::consts::{ - constant, + constant, Constant, Constant::{F32, F64}, }; use crate::utils::*; @@ -37,6 +37,7 @@ declare_clippy_lint! { /// let _ = a.log(E); /// let _ = (1.0 + a).ln(); /// let _ = a.exp() - 1.0; + /// let _ = a.powf(2.0); /// ``` /// /// is better expressed as @@ -54,6 +55,7 @@ declare_clippy_lint! { /// let _ = a.ln(); /// let _ = a.ln_1p(); /// let _ = a.exp_m1(); + /// let _ = a.powi(2); /// ``` pub FLOATING_POINT_IMPROVEMENTS, nursery, @@ -114,6 +116,31 @@ fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { } } +// Returns an integer if the float constant is a whole number and it +// can be converted to an integer without loss +// TODO: Add a better check to determine whether the float can be +// casted without loss +#[allow(clippy::cast_possible_truncation)] +fn get_integer_from_float_constant(value: &Constant) -> Option { + match value { + F32(num) if (num.trunc() - num).abs() <= std::f32::EPSILON => { + if *num > -16_777_217.0 && *num < 16_777_217.0 { + Some(num.round() as i64) + } else { + None + } + }, + F64(num) if (num.trunc() - num).abs() <= std::f64::EPSILON => { + if *num > -9_007_199_254_740_993.0 && *num < 9_007_199_254_740_993.0 { + Some(num.round() as i64) + } else { + None + } + }, + _ => None, + } +} + fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { // Check receiver if let Some((value, _)) = constant(cx, cx.tables, &args[0]) { @@ -149,6 +176,18 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { } else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value { help = "cube-root of a number can be computed more accurately"; method = "cbrt"; + } else if let Some(exponent) = get_integer_from_float_constant(&value) { + span_lint_and_sugg( + cx, + FLOATING_POINT_IMPROVEMENTS, + expr.span, + "exponentiation with integer powers can be computed more efficiently", + "consider using", + format!("{}.powi({})", sugg::Sugg::hir(cx, &args[0], ".."), exponent), + Applicability::MachineApplicable, + ); + + return; } else { return; } diff --git a/tests/ui/floating_point_arithmetic.rs b/tests/ui/floating_point_arithmetic.rs index 1feeb827621a..77a14a7a6668 100644 --- a/tests/ui/floating_point_arithmetic.rs +++ b/tests/ui/floating_point_arithmetic.rs @@ -46,12 +46,24 @@ fn check_powf() { let _ = std::f32::consts::E.powf(x); let _ = x.powf(1.0 / 2.0); let _ = x.powf(1.0 / 3.0); + let _ = x.powf(2.0); + let _ = x.powf(-2.0); + let _ = x.powf(2.1); + let _ = x.powf(-2.1); + let _ = x.powf(16_777_217.0); + let _ = x.powf(-16_777_217.0); let x = 3f64; let _ = 2f64.powf(x); let _ = std::f64::consts::E.powf(x); let _ = x.powf(1.0 / 2.0); let _ = x.powf(1.0 / 3.0); + let _ = x.powf(2.0); + let _ = x.powf(-2.0); + let _ = x.powf(2.1); + let _ = x.powf(-2.1); + let _ = x.powf(9_007_199_254_740_993.0); + let _ = x.powf(-9_007_199_254_740_993.0); } fn check_expm1() { diff --git a/tests/ui/floating_point_arithmetic.stderr b/tests/ui/floating_point_arithmetic.stderr index a7db1669745a..0fc05bce2528 100644 --- a/tests/ui/floating_point_arithmetic.stderr +++ b/tests/ui/floating_point_arithmetic.stderr @@ -120,53 +120,77 @@ error: cube-root of a number can be computed more accurately LL | let _ = x.powf(1.0 / 3.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` +error: exponentiation with integer powers can be computed more efficiently + --> $DIR/floating_point_arithmetic.rs:49:13 + | +LL | let _ = x.powf(2.0); + | ^^^^^^^^^^^ help: consider using: `x.powi(2)` + +error: exponentiation with integer powers can be computed more efficiently + --> $DIR/floating_point_arithmetic.rs:50:13 + | +LL | let _ = x.powf(-2.0); + | ^^^^^^^^^^^^ help: consider using: `x.powi(-2)` + error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:51:13 + --> $DIR/floating_point_arithmetic.rs:57:13 | LL | let _ = 2f64.powf(x); | ^^^^^^^^^^^^ help: consider using: `x.exp2()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:52:13 + --> $DIR/floating_point_arithmetic.rs:58:13 | LL | let _ = std::f64::consts::E.powf(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()` error: square-root of a number can be computed more efficiently and accurately - --> $DIR/floating_point_arithmetic.rs:53:13 + --> $DIR/floating_point_arithmetic.rs:59:13 | LL | let _ = x.powf(1.0 / 2.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()` error: cube-root of a number can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:54:13 + --> $DIR/floating_point_arithmetic.rs:60:13 | LL | let _ = x.powf(1.0 / 3.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` +error: exponentiation with integer powers can be computed more efficiently + --> $DIR/floating_point_arithmetic.rs:61:13 + | +LL | let _ = x.powf(2.0); + | ^^^^^^^^^^^ help: consider using: `x.powi(2)` + +error: exponentiation with integer powers can be computed more efficiently + --> $DIR/floating_point_arithmetic.rs:62:13 + | +LL | let _ = x.powf(-2.0); + | ^^^^^^^^^^^^ help: consider using: `x.powi(-2)` + error: (e.pow(x) - 1) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:59:13 + --> $DIR/floating_point_arithmetic.rs:71:13 | LL | let _ = x.exp() - 1.0; | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` error: (e.pow(x) - 1) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:60:13 + --> $DIR/floating_point_arithmetic.rs:72:13 | LL | let _ = x.exp() - 1.0 + 2.0; | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` error: (e.pow(x) - 1) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:66:13 + --> $DIR/floating_point_arithmetic.rs:78:13 | LL | let _ = x.exp() - 1.0; | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` error: (e.pow(x) - 1) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:67:13 + --> $DIR/floating_point_arithmetic.rs:79:13 | LL | let _ = x.exp() - 1.0 + 2.0; | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` -error: aborting due to 28 previous errors +error: aborting due to 32 previous errors From de7973392402cd34a98c3d7ca2e0c39d60fcada0 Mon Sep 17 00:00:00 2001 From: Krishna Veera Reddy Date: Mon, 16 Dec 2019 18:03:51 -0800 Subject: [PATCH 132/243] Lint expressions of the form `x.log(b) / y.log(b)` --- clippy_lints/src/floating_point_arithmetic.rs | 103 ++++++++++++++++-- tests/ui/floating_point_arithmetic.rs | 26 +++++ tests/ui/floating_point_arithmetic.stderr | 74 ++++++++++++- 3 files changed, 190 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 84a9cac5b634..7f6dac87d04a 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -64,29 +64,31 @@ declare_clippy_lint! { declare_lint_pass!(FloatingPointArithmetic => [FLOATING_POINT_IMPROVEMENTS]); -fn check_log_base(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { - let arg = sugg::Sugg::hir(cx, &args[0], "..").maybe_par(); - - if let Some((value, _)) = constant(cx, cx.tables, &args[1]) { - let method; - +// Returns the specialized log method for a given base if base is constant +// and is one of 2, 10 and e +fn get_specialized_log_method(cx: &LateContext<'_, '_>, base: &Expr) -> Option<&'static str> { + if let Some((value, _)) = constant(cx, cx.tables, base) { if F32(2.0) == value || F64(2.0) == value { - method = "log2"; + return Some("log2"); } else if F32(10.0) == value || F64(10.0) == value { - method = "log10"; + return Some("log10"); } else if F32(f32_consts::E) == value || F64(f64_consts::E) == value { - method = "ln"; - } else { - return; + return Some("ln"); } + } + + None +} +fn check_log_base(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { + if let Some(method) = get_specialized_log_method(cx, &args[1]) { span_lint_and_sugg( cx, FLOATING_POINT_IMPROVEMENTS, expr.span, "logarithm for bases 2, 10 and e can be computed more accurately", "consider using", - format!("{}.{}()", arg, method), + format!("{}.{}()", sugg::Sugg::hir(cx, &args[0], ".."), method), Applicability::MachineApplicable, ); } @@ -232,6 +234,82 @@ fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr) { } } +// Checks whether two expressions evaluate to the same value +fn are_exprs_equivalent(cx: &LateContext<'_, '_>, left: &Expr, right: &Expr) -> bool { + // Checks whether the values are constant and equal + if_chain! { + if let Some((left_value, _)) = constant(cx, cx.tables, left); + if let Some((right_value, _)) = constant(cx, cx.tables, right); + if left_value == right_value; + then { + return true; + } + } + + // Checks whether the expressions resolve to the same variable + if_chain! { + if let ExprKind::Path(ref left_qpath) = left.kind; + if let QPath::Resolved(_, ref left_path) = *left_qpath; + if left_path.segments.len() == 1; + if let def::Res::Local(left_local_id) = qpath_res(cx, left_qpath, left.hir_id); + if let ExprKind::Path(ref right_qpath) = right.kind; + if let QPath::Resolved(_, ref right_path) = *right_qpath; + if right_path.segments.len() == 1; + if let def::Res::Local(right_local_id) = qpath_res(cx, right_qpath, right.hir_id); + if left_local_id == right_local_id; + then { + return true; + } + } + + false +} + +fn check_log_division(cx: &LateContext<'_, '_>, expr: &Expr) { + let log_methods = ["log", "log2", "log10", "ln"]; + + if_chain! { + if let ExprKind::Binary(op, ref lhs, ref rhs) = expr.kind; + if op.node == BinOpKind::Div; + if cx.tables.expr_ty(lhs).is_floating_point(); + if let ExprKind::MethodCall(left_path, _, left_args) = &lhs.kind; + if let ExprKind::MethodCall(right_path, _, right_args) = &rhs.kind; + let left_method = left_path.ident.name.as_str(); + if left_method == right_path.ident.name.as_str(); + if log_methods.iter().any(|&method| left_method == method); + then { + let left_recv = &left_args[0]; + let right_recv = &right_args[0]; + + // Return early when bases are not equal + if left_method == "log" && !are_exprs_equivalent(cx, &left_args[1], &right_args[1]) { + return; + } + + // Reduce the expression further for bases 2, 10 and e + let suggestion = if let Some(method) = get_specialized_log_method(cx, right_recv) { + format!("{}.{}()", sugg::Sugg::hir(cx, left_recv, ".."), method) + } else { + format!( + "{}.log({})", + sugg::Sugg::hir(cx, left_recv, ".."), + sugg::Sugg::hir(cx, right_recv, "..") + ) + }; + + span_lint_and_sugg( + cx, + FLOATING_POINT_IMPROVEMENTS, + expr.span, + "x.log(b) / y.log(b) can be reduced to x.log(y)", + "consider using", + suggestion, + Applicability::MachineApplicable, + ); + } + } +} + impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprKind::MethodCall(ref path, _, args) = &expr.kind { @@ -247,6 +325,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic { } } else { check_expm1(cx, expr); + check_log_division(cx, expr); } } } diff --git a/tests/ui/floating_point_arithmetic.rs b/tests/ui/floating_point_arithmetic.rs index 77a14a7a6668..ff5949415461 100644 --- a/tests/ui/floating_point_arithmetic.rs +++ b/tests/ui/floating_point_arithmetic.rs @@ -82,4 +82,30 @@ fn check_expm1() { let _ = x.exp() - 1.0 * 2.0; } +fn check_log_division() { + let x = 3f32; + let y = 2f32; + let b = 4f32; + + let _ = x.log2() / y.log2(); + let _ = x.log10() / y.log10(); + let _ = x.ln() / y.ln(); + let _ = x.log(4.0) / y.log(4.0); + let _ = x.log(b) / y.log(b); + let _ = x.log(b) / y.log(x); + let _ = x.log(b) / 2f32.log(b); + + let x = 3f64; + let y = 2f64; + let b = 4f64; + + let _ = x.log2() / y.log2(); + let _ = x.log10() / y.log10(); + let _ = x.ln() / y.ln(); + let _ = x.log(4.0) / y.log(4.0); + let _ = x.log(b) / y.log(b); + let _ = x.log(b) / y.log(x); + let _ = x.log(b) / 2f64.log(b); +} + fn main() {} diff --git a/tests/ui/floating_point_arithmetic.stderr b/tests/ui/floating_point_arithmetic.stderr index 0fc05bce2528..076b8d4fefe6 100644 --- a/tests/ui/floating_point_arithmetic.stderr +++ b/tests/ui/floating_point_arithmetic.stderr @@ -192,5 +192,77 @@ error: (e.pow(x) - 1) can be computed more accurately LL | let _ = x.exp() - 1.0 + 2.0; | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` -error: aborting due to 32 previous errors +error: x.log(b) / y.log(b) can be reduced to x.log(y) + --> $DIR/floating_point_arithmetic.rs:90:13 + | +LL | let _ = x.log2() / y.log2(); + | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` + +error: x.log(b) / y.log(b) can be reduced to x.log(y) + --> $DIR/floating_point_arithmetic.rs:91:13 + | +LL | let _ = x.log10() / y.log10(); + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` + +error: x.log(b) / y.log(b) can be reduced to x.log(y) + --> $DIR/floating_point_arithmetic.rs:92:13 + | +LL | let _ = x.ln() / y.ln(); + | ^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` + +error: x.log(b) / y.log(b) can be reduced to x.log(y) + --> $DIR/floating_point_arithmetic.rs:93:13 + | +LL | let _ = x.log(4.0) / y.log(4.0); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` + +error: x.log(b) / y.log(b) can be reduced to x.log(y) + --> $DIR/floating_point_arithmetic.rs:94:13 + | +LL | let _ = x.log(b) / y.log(b); + | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` + +error: x.log(b) / y.log(b) can be reduced to x.log(y) + --> $DIR/floating_point_arithmetic.rs:96:13 + | +LL | let _ = x.log(b) / 2f32.log(b); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log2()` + +error: x.log(b) / y.log(b) can be reduced to x.log(y) + --> $DIR/floating_point_arithmetic.rs:102:13 + | +LL | let _ = x.log2() / y.log2(); + | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` + +error: x.log(b) / y.log(b) can be reduced to x.log(y) + --> $DIR/floating_point_arithmetic.rs:103:13 + | +LL | let _ = x.log10() / y.log10(); + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` + +error: x.log(b) / y.log(b) can be reduced to x.log(y) + --> $DIR/floating_point_arithmetic.rs:104:13 + | +LL | let _ = x.ln() / y.ln(); + | ^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` + +error: x.log(b) / y.log(b) can be reduced to x.log(y) + --> $DIR/floating_point_arithmetic.rs:105:13 + | +LL | let _ = x.log(4.0) / y.log(4.0); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` + +error: x.log(b) / y.log(b) can be reduced to x.log(y) + --> $DIR/floating_point_arithmetic.rs:106:13 + | +LL | let _ = x.log(b) / y.log(b); + | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` + +error: x.log(b) / y.log(b) can be reduced to x.log(y) + --> $DIR/floating_point_arithmetic.rs:108:13 + | +LL | let _ = x.log(b) / 2f64.log(b); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log2()` + +error: aborting due to 44 previous errors From a60ae5d31cea7dff1a5b02b958d3295b474a7c9f Mon Sep 17 00:00:00 2001 From: Krishna Veera Reddy Date: Fri, 20 Dec 2019 17:57:47 -0800 Subject: [PATCH 133/243] Split test cases into separate files --- tests/ui/floating_point_exp.rs | 17 ++ tests/ui/floating_point_exp.stderr | 28 ++++ ...nt_arithmetic.rs => floating_point_log.rs} | 42 ----- ...metic.stderr => floating_point_log.stderr} | 154 ++++-------------- tests/ui/floating_point_powf.rs | 27 +++ tests/ui/floating_point_powf.stderr | 76 +++++++++ 6 files changed, 177 insertions(+), 167 deletions(-) create mode 100644 tests/ui/floating_point_exp.rs create mode 100644 tests/ui/floating_point_exp.stderr rename tests/ui/{floating_point_arithmetic.rs => floating_point_log.rs} (60%) rename tests/ui/{floating_point_arithmetic.stderr => floating_point_log.stderr} (50%) create mode 100644 tests/ui/floating_point_powf.rs create mode 100644 tests/ui/floating_point_powf.stderr diff --git a/tests/ui/floating_point_exp.rs b/tests/ui/floating_point_exp.rs new file mode 100644 index 000000000000..303c6124775c --- /dev/null +++ b/tests/ui/floating_point_exp.rs @@ -0,0 +1,17 @@ +#![warn(clippy::floating_point_improvements)] + +fn main() { + let x = 2f32; + let _ = x.exp() - 1.0; + let _ = x.exp() - 1.0 + 2.0; + // Cases where the lint shouldn't be applied + let _ = x.exp() - 2.0; + let _ = x.exp() - 1.0 * 2.0; + + let x = 2f64; + let _ = x.exp() - 1.0; + let _ = x.exp() - 1.0 + 2.0; + // Cases where the lint shouldn't be applied + let _ = x.exp() - 2.0; + let _ = x.exp() - 1.0 * 2.0; +} diff --git a/tests/ui/floating_point_exp.stderr b/tests/ui/floating_point_exp.stderr new file mode 100644 index 000000000000..783218999458 --- /dev/null +++ b/tests/ui/floating_point_exp.stderr @@ -0,0 +1,28 @@ +error: (e.pow(x) - 1) can be computed more accurately + --> $DIR/floating_point_exp.rs:5:13 + | +LL | let _ = x.exp() - 1.0; + | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` + | + = note: `-D clippy::floating-point-improvements` implied by `-D warnings` + +error: (e.pow(x) - 1) can be computed more accurately + --> $DIR/floating_point_exp.rs:6:13 + | +LL | let _ = x.exp() - 1.0 + 2.0; + | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` + +error: (e.pow(x) - 1) can be computed more accurately + --> $DIR/floating_point_exp.rs:12:13 + | +LL | let _ = x.exp() - 1.0; + | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` + +error: (e.pow(x) - 1) can be computed more accurately + --> $DIR/floating_point_exp.rs:13:13 + | +LL | let _ = x.exp() - 1.0 + 2.0; + | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/floating_point_arithmetic.rs b/tests/ui/floating_point_log.rs similarity index 60% rename from tests/ui/floating_point_arithmetic.rs rename to tests/ui/floating_point_log.rs index ff5949415461..4c01d5e716b0 100644 --- a/tests/ui/floating_point_arithmetic.rs +++ b/tests/ui/floating_point_log.rs @@ -40,48 +40,6 @@ fn check_ln1p() { let _ = (1.0 + x - 2.0).ln(); } -fn check_powf() { - let x = 3f32; - let _ = 2f32.powf(x); - let _ = std::f32::consts::E.powf(x); - let _ = x.powf(1.0 / 2.0); - let _ = x.powf(1.0 / 3.0); - let _ = x.powf(2.0); - let _ = x.powf(-2.0); - let _ = x.powf(2.1); - let _ = x.powf(-2.1); - let _ = x.powf(16_777_217.0); - let _ = x.powf(-16_777_217.0); - - let x = 3f64; - let _ = 2f64.powf(x); - let _ = std::f64::consts::E.powf(x); - let _ = x.powf(1.0 / 2.0); - let _ = x.powf(1.0 / 3.0); - let _ = x.powf(2.0); - let _ = x.powf(-2.0); - let _ = x.powf(2.1); - let _ = x.powf(-2.1); - let _ = x.powf(9_007_199_254_740_993.0); - let _ = x.powf(-9_007_199_254_740_993.0); -} - -fn check_expm1() { - let x = 2f32; - let _ = x.exp() - 1.0; - let _ = x.exp() - 1.0 + 2.0; - // Cases where the lint shouldn't be applied - let _ = x.exp() - 2.0; - let _ = x.exp() - 1.0 * 2.0; - - let x = 2f64; - let _ = x.exp() - 1.0; - let _ = x.exp() - 1.0 + 2.0; - // Cases where the lint shouldn't be applied - let _ = x.exp() - 2.0; - let _ = x.exp() - 1.0 * 2.0; -} - fn check_log_division() { let x = 3f32; let y = 2f32; diff --git a/tests/ui/floating_point_arithmetic.stderr b/tests/ui/floating_point_log.stderr similarity index 50% rename from tests/ui/floating_point_arithmetic.stderr rename to tests/ui/floating_point_log.stderr index 076b8d4fefe6..0a36f8fc69fd 100644 --- a/tests/ui/floating_point_arithmetic.stderr +++ b/tests/ui/floating_point_log.stderr @@ -1,5 +1,5 @@ error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:9:13 + --> $DIR/floating_point_log.rs:9:13 | LL | let _ = x.log(2f32); | ^^^^^^^^^^^ help: consider using: `x.log2()` @@ -7,262 +7,166 @@ LL | let _ = x.log(2f32); = note: `-D clippy::floating-point-improvements` implied by `-D warnings` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:10:13 + --> $DIR/floating_point_log.rs:10:13 | LL | let _ = x.log(10f32); | ^^^^^^^^^^^^ help: consider using: `x.log10()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:11:13 + --> $DIR/floating_point_log.rs:11:13 | LL | let _ = x.log(std::f32::consts::E); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.ln()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:12:13 + --> $DIR/floating_point_log.rs:12:13 | LL | let _ = x.log(TWO); | ^^^^^^^^^^ help: consider using: `x.log2()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:13:13 + --> $DIR/floating_point_log.rs:13:13 | LL | let _ = x.log(E); | ^^^^^^^^ help: consider using: `x.ln()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:16:13 + --> $DIR/floating_point_log.rs:16:13 | LL | let _ = x.log(2f64); | ^^^^^^^^^^^ help: consider using: `x.log2()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:17:13 + --> $DIR/floating_point_log.rs:17:13 | LL | let _ = x.log(10f64); | ^^^^^^^^^^^^ help: consider using: `x.log10()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:18:13 + --> $DIR/floating_point_log.rs:18:13 | LL | let _ = x.log(std::f64::consts::E); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.ln()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:23:13 + --> $DIR/floating_point_log.rs:23:13 | LL | let _ = (1.0 + x).ln(); | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:24:13 + --> $DIR/floating_point_log.rs:24:13 | LL | let _ = (1.0 + x * 2.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:25:13 + --> $DIR/floating_point_log.rs:25:13 | LL | let _ = (1.0 + x.powi(2)).ln(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:26:13 + --> $DIR/floating_point_log.rs:26:13 | LL | let _ = (1.0 + x.powi(2) * 2.0).ln(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x.powi(2) * 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:27:13 + --> $DIR/floating_point_log.rs:27:13 | LL | let _ = (1.0 + (std::f32::consts::E - 1.0)).ln(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `((std::f32::consts::E - 1.0)).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:34:13 + --> $DIR/floating_point_log.rs:34:13 | LL | let _ = (1.0 + x).ln(); | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:35:13 + --> $DIR/floating_point_log.rs:35:13 | LL | let _ = (1.0 + x * 2.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:36:13 + --> $DIR/floating_point_log.rs:36:13 | LL | let _ = (1.0 + x.powi(2)).ln(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` -error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:45:13 - | -LL | let _ = 2f32.powf(x); - | ^^^^^^^^^^^^ help: consider using: `x.exp2()` - -error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:46:13 - | -LL | let _ = std::f32::consts::E.powf(x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()` - -error: square-root of a number can be computed more efficiently and accurately - --> $DIR/floating_point_arithmetic.rs:47:13 - | -LL | let _ = x.powf(1.0 / 2.0); - | ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()` - -error: cube-root of a number can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:48:13 - | -LL | let _ = x.powf(1.0 / 3.0); - | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` - -error: exponentiation with integer powers can be computed more efficiently - --> $DIR/floating_point_arithmetic.rs:49:13 - | -LL | let _ = x.powf(2.0); - | ^^^^^^^^^^^ help: consider using: `x.powi(2)` - -error: exponentiation with integer powers can be computed more efficiently - --> $DIR/floating_point_arithmetic.rs:50:13 - | -LL | let _ = x.powf(-2.0); - | ^^^^^^^^^^^^ help: consider using: `x.powi(-2)` - -error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:57:13 - | -LL | let _ = 2f64.powf(x); - | ^^^^^^^^^^^^ help: consider using: `x.exp2()` - -error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:58:13 - | -LL | let _ = std::f64::consts::E.powf(x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()` - -error: square-root of a number can be computed more efficiently and accurately - --> $DIR/floating_point_arithmetic.rs:59:13 - | -LL | let _ = x.powf(1.0 / 2.0); - | ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()` - -error: cube-root of a number can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:60:13 - | -LL | let _ = x.powf(1.0 / 3.0); - | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` - -error: exponentiation with integer powers can be computed more efficiently - --> $DIR/floating_point_arithmetic.rs:61:13 - | -LL | let _ = x.powf(2.0); - | ^^^^^^^^^^^ help: consider using: `x.powi(2)` - -error: exponentiation with integer powers can be computed more efficiently - --> $DIR/floating_point_arithmetic.rs:62:13 - | -LL | let _ = x.powf(-2.0); - | ^^^^^^^^^^^^ help: consider using: `x.powi(-2)` - -error: (e.pow(x) - 1) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:71:13 - | -LL | let _ = x.exp() - 1.0; - | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` - -error: (e.pow(x) - 1) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:72:13 - | -LL | let _ = x.exp() - 1.0 + 2.0; - | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` - -error: (e.pow(x) - 1) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:78:13 - | -LL | let _ = x.exp() - 1.0; - | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` - -error: (e.pow(x) - 1) can be computed more accurately - --> $DIR/floating_point_arithmetic.rs:79:13 - | -LL | let _ = x.exp() - 1.0 + 2.0; - | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` - error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_arithmetic.rs:90:13 + --> $DIR/floating_point_log.rs:48:13 | LL | let _ = x.log2() / y.log2(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_arithmetic.rs:91:13 + --> $DIR/floating_point_log.rs:49:13 | LL | let _ = x.log10() / y.log10(); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_arithmetic.rs:92:13 + --> $DIR/floating_point_log.rs:50:13 | LL | let _ = x.ln() / y.ln(); | ^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_arithmetic.rs:93:13 + --> $DIR/floating_point_log.rs:51:13 | LL | let _ = x.log(4.0) / y.log(4.0); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_arithmetic.rs:94:13 + --> $DIR/floating_point_log.rs:52:13 | LL | let _ = x.log(b) / y.log(b); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_arithmetic.rs:96:13 + --> $DIR/floating_point_log.rs:54:13 | LL | let _ = x.log(b) / 2f32.log(b); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log2()` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_arithmetic.rs:102:13 + --> $DIR/floating_point_log.rs:60:13 | LL | let _ = x.log2() / y.log2(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_arithmetic.rs:103:13 + --> $DIR/floating_point_log.rs:61:13 | LL | let _ = x.log10() / y.log10(); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_arithmetic.rs:104:13 + --> $DIR/floating_point_log.rs:62:13 | LL | let _ = x.ln() / y.ln(); | ^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_arithmetic.rs:105:13 + --> $DIR/floating_point_log.rs:63:13 | LL | let _ = x.log(4.0) / y.log(4.0); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_arithmetic.rs:106:13 + --> $DIR/floating_point_log.rs:64:13 | LL | let _ = x.log(b) / y.log(b); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_arithmetic.rs:108:13 + --> $DIR/floating_point_log.rs:66:13 | LL | let _ = x.log(b) / 2f64.log(b); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log2()` -error: aborting due to 44 previous errors +error: aborting due to 28 previous errors diff --git a/tests/ui/floating_point_powf.rs b/tests/ui/floating_point_powf.rs new file mode 100644 index 000000000000..14f1f531f0f8 --- /dev/null +++ b/tests/ui/floating_point_powf.rs @@ -0,0 +1,27 @@ +#![warn(clippy::floating_point_improvements)] + +fn main() { + let x = 3f32; + let _ = 2f32.powf(x); + let _ = std::f32::consts::E.powf(x); + let _ = x.powf(1.0 / 2.0); + let _ = x.powf(1.0 / 3.0); + let _ = x.powf(2.0); + let _ = x.powf(-2.0); + let _ = x.powf(2.1); + let _ = x.powf(-2.1); + let _ = x.powf(16_777_217.0); + let _ = x.powf(-16_777_217.0); + + let x = 3f64; + let _ = 2f64.powf(x); + let _ = std::f64::consts::E.powf(x); + let _ = x.powf(1.0 / 2.0); + let _ = x.powf(1.0 / 3.0); + let _ = x.powf(2.0); + let _ = x.powf(-2.0); + let _ = x.powf(2.1); + let _ = x.powf(-2.1); + let _ = x.powf(9_007_199_254_740_993.0); + let _ = x.powf(-9_007_199_254_740_993.0); +} diff --git a/tests/ui/floating_point_powf.stderr b/tests/ui/floating_point_powf.stderr new file mode 100644 index 000000000000..2be54af96c6b --- /dev/null +++ b/tests/ui/floating_point_powf.stderr @@ -0,0 +1,76 @@ +error: exponent for bases 2 and e can be computed more accurately + --> $DIR/floating_point_powf.rs:5:13 + | +LL | let _ = 2f32.powf(x); + | ^^^^^^^^^^^^ help: consider using: `x.exp2()` + | + = note: `-D clippy::floating-point-improvements` implied by `-D warnings` + +error: exponent for bases 2 and e can be computed more accurately + --> $DIR/floating_point_powf.rs:6:13 + | +LL | let _ = std::f32::consts::E.powf(x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()` + +error: square-root of a number can be computed more efficiently and accurately + --> $DIR/floating_point_powf.rs:7:13 + | +LL | let _ = x.powf(1.0 / 2.0); + | ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()` + +error: cube-root of a number can be computed more accurately + --> $DIR/floating_point_powf.rs:8:13 + | +LL | let _ = x.powf(1.0 / 3.0); + | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` + +error: exponentiation with integer powers can be computed more efficiently + --> $DIR/floating_point_powf.rs:9:13 + | +LL | let _ = x.powf(2.0); + | ^^^^^^^^^^^ help: consider using: `x.powi(2)` + +error: exponentiation with integer powers can be computed more efficiently + --> $DIR/floating_point_powf.rs:10:13 + | +LL | let _ = x.powf(-2.0); + | ^^^^^^^^^^^^ help: consider using: `x.powi(-2)` + +error: exponent for bases 2 and e can be computed more accurately + --> $DIR/floating_point_powf.rs:17:13 + | +LL | let _ = 2f64.powf(x); + | ^^^^^^^^^^^^ help: consider using: `x.exp2()` + +error: exponent for bases 2 and e can be computed more accurately + --> $DIR/floating_point_powf.rs:18:13 + | +LL | let _ = std::f64::consts::E.powf(x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()` + +error: square-root of a number can be computed more efficiently and accurately + --> $DIR/floating_point_powf.rs:19:13 + | +LL | let _ = x.powf(1.0 / 2.0); + | ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()` + +error: cube-root of a number can be computed more accurately + --> $DIR/floating_point_powf.rs:20:13 + | +LL | let _ = x.powf(1.0 / 3.0); + | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` + +error: exponentiation with integer powers can be computed more efficiently + --> $DIR/floating_point_powf.rs:21:13 + | +LL | let _ = x.powf(2.0); + | ^^^^^^^^^^^ help: consider using: `x.powi(2)` + +error: exponentiation with integer powers can be computed more efficiently + --> $DIR/floating_point_powf.rs:22:13 + | +LL | let _ = x.powf(-2.0); + | ^^^^^^^^^^^^ help: consider using: `x.powi(-2)` + +error: aborting due to 12 previous errors + From de07c8490332c17deafa89d29724a6483a1765b3 Mon Sep 17 00:00:00 2001 From: Krishna Veera Reddy Date: Fri, 20 Dec 2019 20:07:03 -0800 Subject: [PATCH 134/243] Detect usage of `(x + 1).ln()` and suggest `x.ln_1p()` instead --- clippy_lints/src/floating_point_arithmetic.rs | 14 ++-- tests/ui/floating_point_log.rs | 14 +++- tests/ui/floating_point_log.stderr | 80 +++++++++++++++---- 3 files changed, 84 insertions(+), 24 deletions(-) diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 7f6dac87d04a..6a1351260783 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -94,16 +94,18 @@ fn check_log_base(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { } } -// TODO: Lint expressions of the form `(x + 1).ln()` and `(x + y).ln()` -// where y > 1 and suggest usage of `(x + (y - 1)).ln_1p()` instead +// TODO: Lint expressions of the form `(x + y).ln()` where y > 1 and +// suggest usage of `(x + (y - 1)).ln_1p()` instead fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { if_chain! { if let ExprKind::Binary(op, ref lhs, ref rhs) = &args[0].kind; if op.node == BinOpKind::Add; - if let Some((value, _)) = constant(cx, cx.tables, lhs); - if F32(1.0) == value || F64(1.0) == value; then { - let arg = sugg::Sugg::hir(cx, rhs, "..").maybe_par(); + let recv = match (constant(cx, cx.tables, lhs), constant(cx, cx.tables, rhs)) { + (Some((value, _)), _) if F32(1.0) == value || F64(1.0) == value => rhs, + (_, Some((value, _))) if F32(1.0) == value || F64(1.0) == value => lhs, + _ => return, + }; span_lint_and_sugg( cx, @@ -111,7 +113,7 @@ fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { expr.span, "ln(1 + x) can be computed more accurately", "consider using", - format!("{}.ln_1p()", arg), + format!("{}.ln_1p()", sugg::Sugg::hir(cx, recv, "..").maybe_par()), Applicability::MachineApplicable, ); } diff --git a/tests/ui/floating_point_log.rs b/tests/ui/floating_point_log.rs index 4c01d5e716b0..9a46d2803be3 100644 --- a/tests/ui/floating_point_log.rs +++ b/tests/ui/floating_point_log.rs @@ -25,18 +25,28 @@ fn check_ln1p() { let _ = (1.0 + x.powi(2)).ln(); let _ = (1.0 + x.powi(2) * 2.0).ln(); let _ = (1.0 + (std::f32::consts::E - 1.0)).ln(); - // Cases where the lint shouldn't be applied let _ = (x + 1.0).ln(); + let _ = (x.powi(2) + 1.0).ln(); + let _ = (x + 2.0 + 1.0).ln(); + let _ = (x * 2.0 + 1.0).ln(); + // Cases where the lint shouldn't be applied let _ = (1.0 + x + 2.0).ln(); + let _ = (x + 1.0 + 2.0).ln(); + let _ = (x + 1.0 * 2.0).ln(); let _ = (1.0 + x - 2.0).ln(); let x = 1f64; let _ = (1.0 + x).ln(); let _ = (1.0 + x * 2.0).ln(); let _ = (1.0 + x.powi(2)).ln(); - // Cases where the lint shouldn't be applied let _ = (x + 1.0).ln(); + let _ = (x.powi(2) + 1.0).ln(); + let _ = (x + 2.0 + 1.0).ln(); + let _ = (x * 2.0 + 1.0).ln(); + // Cases where the lint shouldn't be applied let _ = (1.0 + x + 2.0).ln(); + let _ = (x + 1.0 + 2.0).ln(); + let _ = (x + 1.0 * 2.0).ln(); let _ = (1.0 + x - 2.0).ln(); } diff --git a/tests/ui/floating_point_log.stderr b/tests/ui/floating_point_log.stderr index 0a36f8fc69fd..6ae9de02f2ca 100644 --- a/tests/ui/floating_point_log.stderr +++ b/tests/ui/floating_point_log.stderr @@ -79,94 +79,142 @@ LL | let _ = (1.0 + (std::f32::consts::E - 1.0)).ln(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `((std::f32::consts::E - 1.0)).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:34:13 + --> $DIR/floating_point_log.rs:28:13 + | +LL | let _ = (x + 1.0).ln(); + | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_log.rs:29:13 + | +LL | let _ = (x.powi(2) + 1.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_log.rs:30:13 + | +LL | let _ = (x + 2.0 + 1.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x + 2.0).ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_log.rs:31:13 + | +LL | let _ = (x * 2.0 + 1.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_log.rs:39:13 | LL | let _ = (1.0 + x).ln(); | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:35:13 + --> $DIR/floating_point_log.rs:40:13 | LL | let _ = (1.0 + x * 2.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:36:13 + --> $DIR/floating_point_log.rs:41:13 | LL | let _ = (1.0 + x.powi(2)).ln(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_log.rs:42:13 + | +LL | let _ = (x + 1.0).ln(); + | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_log.rs:43:13 + | +LL | let _ = (x.powi(2) + 1.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_log.rs:44:13 + | +LL | let _ = (x + 2.0 + 1.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x + 2.0).ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_log.rs:45:13 + | +LL | let _ = (x * 2.0 + 1.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` + error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:48:13 + --> $DIR/floating_point_log.rs:58:13 | LL | let _ = x.log2() / y.log2(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:49:13 + --> $DIR/floating_point_log.rs:59:13 | LL | let _ = x.log10() / y.log10(); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:50:13 + --> $DIR/floating_point_log.rs:60:13 | LL | let _ = x.ln() / y.ln(); | ^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:51:13 + --> $DIR/floating_point_log.rs:61:13 | LL | let _ = x.log(4.0) / y.log(4.0); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:52:13 + --> $DIR/floating_point_log.rs:62:13 | LL | let _ = x.log(b) / y.log(b); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:54:13 + --> $DIR/floating_point_log.rs:64:13 | LL | let _ = x.log(b) / 2f32.log(b); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log2()` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:60:13 + --> $DIR/floating_point_log.rs:70:13 | LL | let _ = x.log2() / y.log2(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:61:13 + --> $DIR/floating_point_log.rs:71:13 | LL | let _ = x.log10() / y.log10(); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:62:13 + --> $DIR/floating_point_log.rs:72:13 | LL | let _ = x.ln() / y.ln(); | ^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:63:13 + --> $DIR/floating_point_log.rs:73:13 | LL | let _ = x.log(4.0) / y.log(4.0); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:64:13 + --> $DIR/floating_point_log.rs:74:13 | LL | let _ = x.log(b) / y.log(b); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:66:13 + --> $DIR/floating_point_log.rs:76:13 | LL | let _ = x.log(b) / 2f64.log(b); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log2()` -error: aborting due to 28 previous errors +error: aborting due to 36 previous errors From fd2506bcbf99de5f54a40d5156b1bbbca710f6f0 Mon Sep 17 00:00:00 2001 From: Krishna Veera Reddy Date: Fri, 3 Jan 2020 22:19:13 -0800 Subject: [PATCH 135/243] Add type suffixes to unsuffixed method receiver suggestions --- clippy_lints/src/floating_point_arithmetic.rs | 64 ++++++++++++--- tests/ui/floating_point_log.rs | 4 + tests/ui/floating_point_log.stderr | 80 ++++++++++++------- tests/ui/floating_point_powf.rs | 8 ++ tests/ui/floating_point_powf.stderr | 70 +++++++++++++--- 5 files changed, 177 insertions(+), 49 deletions(-) diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 6a1351260783..dbf8e0a9ac47 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -7,10 +7,13 @@ use if_chain::if_chain; use rustc::declare_lint_pass; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::ty; use rustc_errors::Applicability; use rustc_session::declare_tool_lint; use std::f32::consts as f32_consts; use std::f64::consts as f64_consts; +use sugg::Sugg; +use syntax::ast; declare_clippy_lint! { /// **What it does:** Looks for floating-point expressions that @@ -80,7 +83,45 @@ fn get_specialized_log_method(cx: &LateContext<'_, '_>, base: &Expr) -> Option<& None } -fn check_log_base(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { +// Adds type suffixes and parenthesis to method receivers if necessary +fn prepare_receiver_sugg<'a>(cx: &LateContext<'_, '_>, mut expr: &'a Expr<'a>) -> Sugg<'a> { + let mut suggestion = Sugg::hir(cx, expr, ".."); + + if let ExprKind::Unary(UnOp::UnNeg, inner_expr) = &expr.kind { + expr = &inner_expr; + } + + if_chain! { + // if the expression is a float literal and it is unsuffixed then + // add a suffix so the suggestion is valid and unambiguous + if let ty::Float(float_ty) = cx.tables.expr_ty(expr).kind; + if let ExprKind::Lit(lit) = &expr.kind; + if let ast::LitKind::Float(sym, ast::LitFloatType::Unsuffixed) = lit.node; + then { + let op = format!( + "{}{}{}", + suggestion, + // Check for float literals without numbers following the decimal + // separator such as `2.` and adds a trailing zero + if sym.as_str().ends_with('.') { + "0" + } else { + "" + }, + float_ty.name_str() + ).into(); + + suggestion = match suggestion { + Sugg::MaybeParen(_) => Sugg::MaybeParen(op), + _ => Sugg::NonParen(op) + }; + } + } + + suggestion.maybe_par() +} + +fn check_log_base(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { if let Some(method) = get_specialized_log_method(cx, &args[1]) { span_lint_and_sugg( cx, @@ -88,7 +129,7 @@ fn check_log_base(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { expr.span, "logarithm for bases 2, 10 and e can be computed more accurately", "consider using", - format!("{}.{}()", sugg::Sugg::hir(cx, &args[0], ".."), method), + format!("{}.{}()", Sugg::hir(cx, &args[0], ".."), method), Applicability::MachineApplicable, ); } @@ -113,7 +154,7 @@ fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { expr.span, "ln(1 + x) can be computed more accurately", "consider using", - format!("{}.ln_1p()", sugg::Sugg::hir(cx, recv, "..").maybe_par()), + format!("{}.ln_1p()", prepare_receiver_sugg(cx, recv)), Applicability::MachineApplicable, ); } @@ -164,7 +205,7 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { expr.span, "exponent for bases 2 and e can be computed more accurately", "consider using", - format!("{}.{}()", sugg::Sugg::hir(cx, &args[1], "..").maybe_par(), method), + format!("{}.{}()", prepare_receiver_sugg(cx, &args[1]), method), Applicability::MachineApplicable, ); } @@ -187,7 +228,7 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { expr.span, "exponentiation with integer powers can be computed more efficiently", "consider using", - format!("{}.powi({})", sugg::Sugg::hir(cx, &args[0], ".."), exponent), + format!("{}.powi({})", Sugg::hir(cx, &args[0], ".."), exponent), Applicability::MachineApplicable, ); @@ -202,7 +243,7 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { expr.span, help, "consider using", - format!("{}.{}()", sugg::Sugg::hir(cx, &args[0], ".."), method), + format!("{}.{}()", Sugg::hir(cx, &args[0], ".."), method), Applicability::MachineApplicable, ); } @@ -218,6 +259,7 @@ fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr) { if let Some((value, _)) = constant(cx, cx.tables, rhs); if F32(1.0) == value || F64(1.0) == value; if let ExprKind::MethodCall(ref path, _, ref method_args) = lhs.kind; + if cx.tables.expr_ty(&method_args[0]).is_floating_point(); if path.ident.name.as_str() == "exp"; then { span_lint_and_sugg( @@ -228,7 +270,7 @@ fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr) { "consider using", format!( "{}.exp_m1()", - sugg::Sugg::hir(cx, &method_args[0], "..") + Sugg::hir(cx, &method_args[0], "..") ), Applicability::MachineApplicable, ); @@ -275,7 +317,9 @@ fn check_log_division(cx: &LateContext<'_, '_>, expr: &Expr) { if op.node == BinOpKind::Div; if cx.tables.expr_ty(lhs).is_floating_point(); if let ExprKind::MethodCall(left_path, _, left_args) = &lhs.kind; + if cx.tables.expr_ty(&left_args[0]).is_floating_point(); if let ExprKind::MethodCall(right_path, _, right_args) = &rhs.kind; + if cx.tables.expr_ty(&right_args[0]).is_floating_point(); let left_method = left_path.ident.name.as_str(); if left_method == right_path.ident.name.as_str(); if log_methods.iter().any(|&method| left_method == method); @@ -290,12 +334,12 @@ fn check_log_division(cx: &LateContext<'_, '_>, expr: &Expr) { // Reduce the expression further for bases 2, 10 and e let suggestion = if let Some(method) = get_specialized_log_method(cx, right_recv) { - format!("{}.{}()", sugg::Sugg::hir(cx, left_recv, ".."), method) + format!("{}.{}()", Sugg::hir(cx, left_recv, ".."), method) } else { format!( "{}.log({})", - sugg::Sugg::hir(cx, left_recv, ".."), - sugg::Sugg::hir(cx, right_recv, "..") + Sugg::hir(cx, left_recv, ".."), + Sugg::hir(cx, right_recv, "..") ) }; diff --git a/tests/ui/floating_point_log.rs b/tests/ui/floating_point_log.rs index 9a46d2803be3..5775d8715d46 100644 --- a/tests/ui/floating_point_log.rs +++ b/tests/ui/floating_point_log.rs @@ -20,6 +20,8 @@ fn check_log_base() { fn check_ln1p() { let x = 1f32; + let _ = (1f32 + 2.).ln(); + let _ = (1f32 + 2.0).ln(); let _ = (1.0 + x).ln(); let _ = (1.0 + x * 2.0).ln(); let _ = (1.0 + x.powi(2)).ln(); @@ -36,6 +38,8 @@ fn check_ln1p() { let _ = (1.0 + x - 2.0).ln(); let x = 1f64; + let _ = (1f64 + 2.).ln(); + let _ = (1f64 + 2.0).ln(); let _ = (1.0 + x).ln(); let _ = (1.0 + x * 2.0).ln(); let _ = (1.0 + x.powi(2)).ln(); diff --git a/tests/ui/floating_point_log.stderr b/tests/ui/floating_point_log.stderr index 6ae9de02f2ca..cd3142e041a2 100644 --- a/tests/ui/floating_point_log.stderr +++ b/tests/ui/floating_point_log.stderr @@ -51,170 +51,194 @@ LL | let _ = x.log(std::f64::consts::E); error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:23:13 | +LL | let _ = (1f32 + 2.).ln(); + | ^^^^^^^^^^^^^^^^ help: consider using: `2.0f32.ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_log.rs:24:13 + | +LL | let _ = (1f32 + 2.0).ln(); + | ^^^^^^^^^^^^^^^^^ help: consider using: `2.0f32.ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_log.rs:25:13 + | LL | let _ = (1.0 + x).ln(); | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:24:13 + --> $DIR/floating_point_log.rs:26:13 | LL | let _ = (1.0 + x * 2.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:25:13 + --> $DIR/floating_point_log.rs:27:13 | LL | let _ = (1.0 + x.powi(2)).ln(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:26:13 + --> $DIR/floating_point_log.rs:28:13 | LL | let _ = (1.0 + x.powi(2) * 2.0).ln(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x.powi(2) * 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:27:13 + --> $DIR/floating_point_log.rs:29:13 | LL | let _ = (1.0 + (std::f32::consts::E - 1.0)).ln(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `((std::f32::consts::E - 1.0)).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:28:13 + --> $DIR/floating_point_log.rs:30:13 | LL | let _ = (x + 1.0).ln(); | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:29:13 + --> $DIR/floating_point_log.rs:31:13 | LL | let _ = (x.powi(2) + 1.0).ln(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:30:13 + --> $DIR/floating_point_log.rs:32:13 | LL | let _ = (x + 2.0 + 1.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x + 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:31:13 + --> $DIR/floating_point_log.rs:33:13 | LL | let _ = (x * 2.0 + 1.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:39:13 + --> $DIR/floating_point_log.rs:41:13 + | +LL | let _ = (1f64 + 2.).ln(); + | ^^^^^^^^^^^^^^^^ help: consider using: `2.0f64.ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_log.rs:42:13 + | +LL | let _ = (1f64 + 2.0).ln(); + | ^^^^^^^^^^^^^^^^^ help: consider using: `2.0f64.ln_1p()` + +error: ln(1 + x) can be computed more accurately + --> $DIR/floating_point_log.rs:43:13 | LL | let _ = (1.0 + x).ln(); | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:40:13 + --> $DIR/floating_point_log.rs:44:13 | LL | let _ = (1.0 + x * 2.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:41:13 + --> $DIR/floating_point_log.rs:45:13 | LL | let _ = (1.0 + x.powi(2)).ln(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:42:13 + --> $DIR/floating_point_log.rs:46:13 | LL | let _ = (x + 1.0).ln(); | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:43:13 + --> $DIR/floating_point_log.rs:47:13 | LL | let _ = (x.powi(2) + 1.0).ln(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:44:13 + --> $DIR/floating_point_log.rs:48:13 | LL | let _ = (x + 2.0 + 1.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x + 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:45:13 + --> $DIR/floating_point_log.rs:49:13 | LL | let _ = (x * 2.0 + 1.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:58:13 + --> $DIR/floating_point_log.rs:62:13 | LL | let _ = x.log2() / y.log2(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:59:13 + --> $DIR/floating_point_log.rs:63:13 | LL | let _ = x.log10() / y.log10(); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:60:13 + --> $DIR/floating_point_log.rs:64:13 | LL | let _ = x.ln() / y.ln(); | ^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:61:13 + --> $DIR/floating_point_log.rs:65:13 | LL | let _ = x.log(4.0) / y.log(4.0); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:62:13 + --> $DIR/floating_point_log.rs:66:13 | LL | let _ = x.log(b) / y.log(b); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:64:13 + --> $DIR/floating_point_log.rs:68:13 | LL | let _ = x.log(b) / 2f32.log(b); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log2()` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:70:13 + --> $DIR/floating_point_log.rs:74:13 | LL | let _ = x.log2() / y.log2(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:71:13 + --> $DIR/floating_point_log.rs:75:13 | LL | let _ = x.log10() / y.log10(); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:72:13 + --> $DIR/floating_point_log.rs:76:13 | LL | let _ = x.ln() / y.ln(); | ^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:73:13 + --> $DIR/floating_point_log.rs:77:13 | LL | let _ = x.log(4.0) / y.log(4.0); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:74:13 + --> $DIR/floating_point_log.rs:78:13 | LL | let _ = x.log(b) / y.log(b); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:76:13 + --> $DIR/floating_point_log.rs:80:13 | LL | let _ = x.log(b) / 2f64.log(b); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log2()` -error: aborting due to 36 previous errors +error: aborting due to 40 previous errors diff --git a/tests/ui/floating_point_powf.rs b/tests/ui/floating_point_powf.rs index 14f1f531f0f8..97a1d93a8019 100644 --- a/tests/ui/floating_point_powf.rs +++ b/tests/ui/floating_point_powf.rs @@ -3,7 +3,11 @@ fn main() { let x = 3f32; let _ = 2f32.powf(x); + let _ = 2f32.powf(3.1); + let _ = 2f32.powf(-3.1); let _ = std::f32::consts::E.powf(x); + let _ = std::f32::consts::E.powf(3.1); + let _ = std::f32::consts::E.powf(-3.1); let _ = x.powf(1.0 / 2.0); let _ = x.powf(1.0 / 3.0); let _ = x.powf(2.0); @@ -15,7 +19,11 @@ fn main() { let x = 3f64; let _ = 2f64.powf(x); + let _ = 2f64.powf(3.1); + let _ = 2f64.powf(-3.1); let _ = std::f64::consts::E.powf(x); + let _ = std::f64::consts::E.powf(3.1); + let _ = std::f64::consts::E.powf(-3.1); let _ = x.powf(1.0 / 2.0); let _ = x.powf(1.0 / 3.0); let _ = x.powf(2.0); diff --git a/tests/ui/floating_point_powf.stderr b/tests/ui/floating_point_powf.stderr index 2be54af96c6b..4e16e7af0465 100644 --- a/tests/ui/floating_point_powf.stderr +++ b/tests/ui/floating_point_powf.stderr @@ -9,68 +9,116 @@ LL | let _ = 2f32.powf(x); error: exponent for bases 2 and e can be computed more accurately --> $DIR/floating_point_powf.rs:6:13 | +LL | let _ = 2f32.powf(3.1); + | ^^^^^^^^^^^^^^ help: consider using: `3.1f32.exp2()` + +error: exponent for bases 2 and e can be computed more accurately + --> $DIR/floating_point_powf.rs:7:13 + | +LL | let _ = 2f32.powf(-3.1); + | ^^^^^^^^^^^^^^^ help: consider using: `(-3.1f32).exp2()` + +error: exponent for bases 2 and e can be computed more accurately + --> $DIR/floating_point_powf.rs:8:13 + | LL | let _ = std::f32::consts::E.powf(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()` +error: exponent for bases 2 and e can be computed more accurately + --> $DIR/floating_point_powf.rs:9:13 + | +LL | let _ = std::f32::consts::E.powf(3.1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `3.1f32.exp()` + +error: exponent for bases 2 and e can be computed more accurately + --> $DIR/floating_point_powf.rs:10:13 + | +LL | let _ = std::f32::consts::E.powf(-3.1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-3.1f32).exp()` + error: square-root of a number can be computed more efficiently and accurately - --> $DIR/floating_point_powf.rs:7:13 + --> $DIR/floating_point_powf.rs:11:13 | LL | let _ = x.powf(1.0 / 2.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()` error: cube-root of a number can be computed more accurately - --> $DIR/floating_point_powf.rs:8:13 + --> $DIR/floating_point_powf.rs:12:13 | LL | let _ = x.powf(1.0 / 3.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` error: exponentiation with integer powers can be computed more efficiently - --> $DIR/floating_point_powf.rs:9:13 + --> $DIR/floating_point_powf.rs:13:13 | LL | let _ = x.powf(2.0); | ^^^^^^^^^^^ help: consider using: `x.powi(2)` error: exponentiation with integer powers can be computed more efficiently - --> $DIR/floating_point_powf.rs:10:13 + --> $DIR/floating_point_powf.rs:14:13 | LL | let _ = x.powf(-2.0); | ^^^^^^^^^^^^ help: consider using: `x.powi(-2)` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:17:13 + --> $DIR/floating_point_powf.rs:21:13 | LL | let _ = 2f64.powf(x); | ^^^^^^^^^^^^ help: consider using: `x.exp2()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:18:13 + --> $DIR/floating_point_powf.rs:22:13 + | +LL | let _ = 2f64.powf(3.1); + | ^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp2()` + +error: exponent for bases 2 and e can be computed more accurately + --> $DIR/floating_point_powf.rs:23:13 + | +LL | let _ = 2f64.powf(-3.1); + | ^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp2()` + +error: exponent for bases 2 and e can be computed more accurately + --> $DIR/floating_point_powf.rs:24:13 | LL | let _ = std::f64::consts::E.powf(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()` +error: exponent for bases 2 and e can be computed more accurately + --> $DIR/floating_point_powf.rs:25:13 + | +LL | let _ = std::f64::consts::E.powf(3.1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp()` + +error: exponent for bases 2 and e can be computed more accurately + --> $DIR/floating_point_powf.rs:26:13 + | +LL | let _ = std::f64::consts::E.powf(-3.1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp()` + error: square-root of a number can be computed more efficiently and accurately - --> $DIR/floating_point_powf.rs:19:13 + --> $DIR/floating_point_powf.rs:27:13 | LL | let _ = x.powf(1.0 / 2.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()` error: cube-root of a number can be computed more accurately - --> $DIR/floating_point_powf.rs:20:13 + --> $DIR/floating_point_powf.rs:28:13 | LL | let _ = x.powf(1.0 / 3.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` error: exponentiation with integer powers can be computed more efficiently - --> $DIR/floating_point_powf.rs:21:13 + --> $DIR/floating_point_powf.rs:29:13 | LL | let _ = x.powf(2.0); | ^^^^^^^^^^^ help: consider using: `x.powi(2)` error: exponentiation with integer powers can be computed more efficiently - --> $DIR/floating_point_powf.rs:22:13 + --> $DIR/floating_point_powf.rs:30:13 | LL | let _ = x.powf(-2.0); | ^^^^^^^^^^^^ help: consider using: `x.powi(-2)` -error: aborting due to 12 previous errors +error: aborting due to 20 previous errors From bc03f465c3801887aa53b0f6eaf35d9b55827b95 Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Mon, 17 Feb 2020 11:38:35 -0800 Subject: [PATCH 136/243] Remove lint for logarithm division identity --- clippy_lints/src/floating_point_arithmetic.rs | 86 +------------------ tests/ui/floating_point_log.rs | 26 ------ tests/ui/floating_point_log.stderr | 74 +--------------- 3 files changed, 4 insertions(+), 182 deletions(-) diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index dbf8e0a9ac47..17babb46daad 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -4,12 +4,11 @@ use crate::consts::{ }; use crate::utils::*; use if_chain::if_chain; -use rustc::declare_lint_pass; -use rustc::hir::*; -use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc_hir::*; +use rustc_lint::{LateContext, LateLintPass}; use rustc::ty; use rustc_errors::Applicability; -use rustc_session::declare_tool_lint; +use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::f32::consts as f32_consts; use std::f64::consts as f64_consts; use sugg::Sugg; @@ -278,84 +277,6 @@ fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr) { } } -// Checks whether two expressions evaluate to the same value -fn are_exprs_equivalent(cx: &LateContext<'_, '_>, left: &Expr, right: &Expr) -> bool { - // Checks whether the values are constant and equal - if_chain! { - if let Some((left_value, _)) = constant(cx, cx.tables, left); - if let Some((right_value, _)) = constant(cx, cx.tables, right); - if left_value == right_value; - then { - return true; - } - } - - // Checks whether the expressions resolve to the same variable - if_chain! { - if let ExprKind::Path(ref left_qpath) = left.kind; - if let QPath::Resolved(_, ref left_path) = *left_qpath; - if left_path.segments.len() == 1; - if let def::Res::Local(left_local_id) = qpath_res(cx, left_qpath, left.hir_id); - if let ExprKind::Path(ref right_qpath) = right.kind; - if let QPath::Resolved(_, ref right_path) = *right_qpath; - if right_path.segments.len() == 1; - if let def::Res::Local(right_local_id) = qpath_res(cx, right_qpath, right.hir_id); - if left_local_id == right_local_id; - then { - return true; - } - } - - false -} - -fn check_log_division(cx: &LateContext<'_, '_>, expr: &Expr) { - let log_methods = ["log", "log2", "log10", "ln"]; - - if_chain! { - if let ExprKind::Binary(op, ref lhs, ref rhs) = expr.kind; - if op.node == BinOpKind::Div; - if cx.tables.expr_ty(lhs).is_floating_point(); - if let ExprKind::MethodCall(left_path, _, left_args) = &lhs.kind; - if cx.tables.expr_ty(&left_args[0]).is_floating_point(); - if let ExprKind::MethodCall(right_path, _, right_args) = &rhs.kind; - if cx.tables.expr_ty(&right_args[0]).is_floating_point(); - let left_method = left_path.ident.name.as_str(); - if left_method == right_path.ident.name.as_str(); - if log_methods.iter().any(|&method| left_method == method); - then { - let left_recv = &left_args[0]; - let right_recv = &right_args[0]; - - // Return early when bases are not equal - if left_method == "log" && !are_exprs_equivalent(cx, &left_args[1], &right_args[1]) { - return; - } - - // Reduce the expression further for bases 2, 10 and e - let suggestion = if let Some(method) = get_specialized_log_method(cx, right_recv) { - format!("{}.{}()", Sugg::hir(cx, left_recv, ".."), method) - } else { - format!( - "{}.log({})", - Sugg::hir(cx, left_recv, ".."), - Sugg::hir(cx, right_recv, "..") - ) - }; - - span_lint_and_sugg( - cx, - FLOATING_POINT_IMPROVEMENTS, - expr.span, - "x.log(b) / y.log(b) can be reduced to x.log(y)", - "consider using", - suggestion, - Applicability::MachineApplicable, - ); - } - } -} - impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprKind::MethodCall(ref path, _, args) = &expr.kind { @@ -371,7 +292,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic { } } else { check_expm1(cx, expr); - check_log_division(cx, expr); } } } diff --git a/tests/ui/floating_point_log.rs b/tests/ui/floating_point_log.rs index 5775d8715d46..18b7686280ec 100644 --- a/tests/ui/floating_point_log.rs +++ b/tests/ui/floating_point_log.rs @@ -54,30 +54,4 @@ fn check_ln1p() { let _ = (1.0 + x - 2.0).ln(); } -fn check_log_division() { - let x = 3f32; - let y = 2f32; - let b = 4f32; - - let _ = x.log2() / y.log2(); - let _ = x.log10() / y.log10(); - let _ = x.ln() / y.ln(); - let _ = x.log(4.0) / y.log(4.0); - let _ = x.log(b) / y.log(b); - let _ = x.log(b) / y.log(x); - let _ = x.log(b) / 2f32.log(b); - - let x = 3f64; - let y = 2f64; - let b = 4f64; - - let _ = x.log2() / y.log2(); - let _ = x.log10() / y.log10(); - let _ = x.ln() / y.ln(); - let _ = x.log(4.0) / y.log(4.0); - let _ = x.log(b) / y.log(b); - let _ = x.log(b) / y.log(x); - let _ = x.log(b) / 2f64.log(b); -} - fn main() {} diff --git a/tests/ui/floating_point_log.stderr b/tests/ui/floating_point_log.stderr index cd3142e041a2..c169745ddf94 100644 --- a/tests/ui/floating_point_log.stderr +++ b/tests/ui/floating_point_log.stderr @@ -168,77 +168,5 @@ error: ln(1 + x) can be computed more accurately LL | let _ = (x * 2.0 + 1.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` -error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:62:13 - | -LL | let _ = x.log2() / y.log2(); - | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` - -error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:63:13 - | -LL | let _ = x.log10() / y.log10(); - | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` - -error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:64:13 - | -LL | let _ = x.ln() / y.ln(); - | ^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` - -error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:65:13 - | -LL | let _ = x.log(4.0) / y.log(4.0); - | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` - -error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:66:13 - | -LL | let _ = x.log(b) / y.log(b); - | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` - -error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:68:13 - | -LL | let _ = x.log(b) / 2f32.log(b); - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log2()` - -error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:74:13 - | -LL | let _ = x.log2() / y.log2(); - | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` - -error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:75:13 - | -LL | let _ = x.log10() / y.log10(); - | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` - -error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:76:13 - | -LL | let _ = x.ln() / y.ln(); - | ^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` - -error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:77:13 - | -LL | let _ = x.log(4.0) / y.log(4.0); - | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` - -error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:78:13 - | -LL | let _ = x.log(b) / y.log(b); - | ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)` - -error: x.log(b) / y.log(b) can be reduced to x.log(y) - --> $DIR/floating_point_log.rs:80:13 - | -LL | let _ = x.log(b) / 2f64.log(b); - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log2()` - -error: aborting due to 40 previous errors +error: aborting due to 28 previous errors From 6dacb1aa678046940d3fae7a68bd0112accecfd4 Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Mon, 17 Feb 2020 12:56:55 -0800 Subject: [PATCH 137/243] Change lint name to `suboptimal_flops` --- CHANGELOG.md | 1 + clippy_lints/src/floating_point_arithmetic.rs | 39 +++++++++---------- clippy_lints/src/lib.rs | 3 +- src/lintlist/mod.rs | 7 ++++ tests/ui/floating_point_exp.rs | 2 +- tests/ui/floating_point_exp.stderr | 2 +- tests/ui/floating_point_log.rs | 2 +- tests/ui/floating_point_log.stderr | 2 +- tests/ui/floating_point_powf.rs | 6 +-- tests/ui/floating_point_powf.stderr | 22 +++++------ 10 files changed, 45 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e99342e4a42..87ece835f7f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1349,6 +1349,7 @@ Released 2018-09-13 [`string_lit_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_lit_as_bytes [`string_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_to_string [`struct_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools +[`suboptimal_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#suboptimal_flops [`suspicious_arithmetic_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_arithmetic_impl [`suspicious_assignment_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_assignment_formatting [`suspicious_else_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_else_formatting diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 17babb46daad..61938405d92d 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -4,10 +4,10 @@ use crate::consts::{ }; use crate::utils::*; use if_chain::if_chain; -use rustc_hir::*; -use rustc_lint::{LateContext, LateLintPass}; use rustc::ty; use rustc_errors::Applicability; +use rustc_hir::*; +use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::f32::consts as f32_consts; use std::f64::consts as f64_consts; @@ -16,11 +16,10 @@ use syntax::ast; declare_clippy_lint! { /// **What it does:** Looks for floating-point expressions that - /// can be expressed using built-in methods to improve accuracy, - /// performance and/or succinctness. + /// can be expressed using built-in methods to improve both + /// accuracy and performance. /// - /// **Why is this bad?** Negatively affects accuracy, performance - /// and/or readability. + /// **Why is this bad?** Negatively impacts accuracy and performance. /// /// **Known problems:** None /// @@ -59,16 +58,16 @@ declare_clippy_lint! { /// let _ = a.exp_m1(); /// let _ = a.powi(2); /// ``` - pub FLOATING_POINT_IMPROVEMENTS, + pub SUBOPTIMAL_FLOPS, nursery, - "looks for improvements to floating-point expressions" + "usage of sub-optimal floating point operations" } -declare_lint_pass!(FloatingPointArithmetic => [FLOATING_POINT_IMPROVEMENTS]); +declare_lint_pass!(FloatingPointArithmetic => [SUBOPTIMAL_FLOPS]); // Returns the specialized log method for a given base if base is constant // and is one of 2, 10 and e -fn get_specialized_log_method(cx: &LateContext<'_, '_>, base: &Expr) -> Option<&'static str> { +fn get_specialized_log_method(cx: &LateContext<'_, '_>, base: &Expr<'_>) -> Option<&'static str> { if let Some((value, _)) = constant(cx, cx.tables, base) { if F32(2.0) == value || F64(2.0) == value { return Some("log2"); @@ -124,7 +123,7 @@ fn check_log_base(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) if let Some(method) = get_specialized_log_method(cx, &args[1]) { span_lint_and_sugg( cx, - FLOATING_POINT_IMPROVEMENTS, + SUBOPTIMAL_FLOPS, expr.span, "logarithm for bases 2, 10 and e can be computed more accurately", "consider using", @@ -136,7 +135,7 @@ fn check_log_base(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) // TODO: Lint expressions of the form `(x + y).ln()` where y > 1 and // suggest usage of `(x + (y - 1)).ln_1p()` instead -fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { +fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { if_chain! { if let ExprKind::Binary(op, ref lhs, ref rhs) = &args[0].kind; if op.node == BinOpKind::Add; @@ -149,7 +148,7 @@ fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { span_lint_and_sugg( cx, - FLOATING_POINT_IMPROVEMENTS, + SUBOPTIMAL_FLOPS, expr.span, "ln(1 + x) can be computed more accurately", "consider using", @@ -185,7 +184,7 @@ fn get_integer_from_float_constant(value: &Constant) -> Option { } } -fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { +fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { // Check receiver if let Some((value, _)) = constant(cx, cx.tables, &args[0]) { let method; @@ -200,7 +199,7 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { span_lint_and_sugg( cx, - FLOATING_POINT_IMPROVEMENTS, + SUBOPTIMAL_FLOPS, expr.span, "exponent for bases 2 and e can be computed more accurately", "consider using", @@ -223,7 +222,7 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { } else if let Some(exponent) = get_integer_from_float_constant(&value) { span_lint_and_sugg( cx, - FLOATING_POINT_IMPROVEMENTS, + SUBOPTIMAL_FLOPS, expr.span, "exponentiation with integer powers can be computed more efficiently", "consider using", @@ -238,7 +237,7 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { span_lint_and_sugg( cx, - FLOATING_POINT_IMPROVEMENTS, + SUBOPTIMAL_FLOPS, expr.span, help, "consider using", @@ -250,7 +249,7 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec) { // TODO: Lint expressions of the form `x.exp() - y` where y > 1 // and suggest usage of `x.exp_m1() - (y - 1)` instead -fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr) { +fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { if_chain! { if let ExprKind::Binary(op, ref lhs, ref rhs) = expr.kind; if op.node == BinOpKind::Sub; @@ -263,7 +262,7 @@ fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr) { then { span_lint_and_sugg( cx, - FLOATING_POINT_IMPROVEMENTS, + SUBOPTIMAL_FLOPS, expr.span, "(e.pow(x) - 1) can be computed more accurately", "consider using", @@ -278,7 +277,7 @@ fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr) { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::MethodCall(ref path, _, args) = &expr.kind { let recv_ty = cx.tables.expr_ty(&args[0]); diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9154a0dc3fff..59ad7e7a651a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -538,6 +538,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &fallible_impl_from::FALLIBLE_IMPL_FROM, &float_literal::EXCESSIVE_PRECISION, &float_literal::LOSSY_FLOAT_LITERAL, + &floating_point_arithmetic::SUBOPTIMAL_FLOPS, &format::USELESS_FORMAT, &formatting::POSSIBLE_MISSING_COMMA, &formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, @@ -1649,7 +1650,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![ LintId::of(&attrs::EMPTY_LINE_AFTER_OUTER_ATTR), LintId::of(&fallible_impl_from::FALLIBLE_IMPL_FROM), - LintId::of(&floating_point_arithmetic::FLOATING_POINT_IMPROVEMENTS), + LintId::of(&floating_point_arithmetic::SUBOPTIMAL_FLOPS), LintId::of(&missing_const_for_fn::MISSING_CONST_FOR_FN), LintId::of(&mul_add::MANUAL_MUL_ADD), LintId::of(&mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 29b5a7ba08a2..de086f863e01 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1960,6 +1960,13 @@ pub const ALL_LINTS: [Lint; 357] = [ deprecation: None, module: "excessive_bools", }, + Lint { + name: "suboptimal_flops", + group: "nursery", + desc: "usage of sub-optimal floating point operations", + deprecation: None, + module: "floating_point_arithmetic", + }, Lint { name: "suspicious_arithmetic_impl", group: "correctness", diff --git a/tests/ui/floating_point_exp.rs b/tests/ui/floating_point_exp.rs index 303c6124775c..c7fe0d035689 100644 --- a/tests/ui/floating_point_exp.rs +++ b/tests/ui/floating_point_exp.rs @@ -1,4 +1,4 @@ -#![warn(clippy::floating_point_improvements)] +#![warn(clippy::suboptimal_flops)] fn main() { let x = 2f32; diff --git a/tests/ui/floating_point_exp.stderr b/tests/ui/floating_point_exp.stderr index 783218999458..83adca8a46c9 100644 --- a/tests/ui/floating_point_exp.stderr +++ b/tests/ui/floating_point_exp.stderr @@ -4,7 +4,7 @@ error: (e.pow(x) - 1) can be computed more accurately LL | let _ = x.exp() - 1.0; | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` | - = note: `-D clippy::floating-point-improvements` implied by `-D warnings` + = note: `-D clippy::suboptimal-flops` implied by `-D warnings` error: (e.pow(x) - 1) can be computed more accurately --> $DIR/floating_point_exp.rs:6:13 diff --git a/tests/ui/floating_point_log.rs b/tests/ui/floating_point_log.rs index 18b7686280ec..c26f71f3067d 100644 --- a/tests/ui/floating_point_log.rs +++ b/tests/ui/floating_point_log.rs @@ -1,5 +1,5 @@ #![allow(dead_code)] -#![warn(clippy::floating_point_improvements)] +#![warn(clippy::suboptimal_flops)] const TWO: f32 = 2.0; const E: f32 = std::f32::consts::E; diff --git a/tests/ui/floating_point_log.stderr b/tests/ui/floating_point_log.stderr index c169745ddf94..db2fc999b6c3 100644 --- a/tests/ui/floating_point_log.stderr +++ b/tests/ui/floating_point_log.stderr @@ -4,7 +4,7 @@ error: logarithm for bases 2, 10 and e can be computed more accurately LL | let _ = x.log(2f32); | ^^^^^^^^^^^ help: consider using: `x.log2()` | - = note: `-D clippy::floating-point-improvements` implied by `-D warnings` + = note: `-D clippy::suboptimal-flops` implied by `-D warnings` error: logarithm for bases 2, 10 and e can be computed more accurately --> $DIR/floating_point_log.rs:10:13 diff --git a/tests/ui/floating_point_powf.rs b/tests/ui/floating_point_powf.rs index 97a1d93a8019..2076821b5b04 100644 --- a/tests/ui/floating_point_powf.rs +++ b/tests/ui/floating_point_powf.rs @@ -1,4 +1,4 @@ -#![warn(clippy::floating_point_improvements)] +#![warn(clippy::suboptimal_flops)] fn main() { let x = 3f32; @@ -14,8 +14,6 @@ fn main() { let _ = x.powf(-2.0); let _ = x.powf(2.1); let _ = x.powf(-2.1); - let _ = x.powf(16_777_217.0); - let _ = x.powf(-16_777_217.0); let x = 3f64; let _ = 2f64.powf(x); @@ -30,6 +28,4 @@ fn main() { let _ = x.powf(-2.0); let _ = x.powf(2.1); let _ = x.powf(-2.1); - let _ = x.powf(9_007_199_254_740_993.0); - let _ = x.powf(-9_007_199_254_740_993.0); } diff --git a/tests/ui/floating_point_powf.stderr b/tests/ui/floating_point_powf.stderr index 4e16e7af0465..35e0c5e56fd8 100644 --- a/tests/ui/floating_point_powf.stderr +++ b/tests/ui/floating_point_powf.stderr @@ -4,7 +4,7 @@ error: exponent for bases 2 and e can be computed more accurately LL | let _ = 2f32.powf(x); | ^^^^^^^^^^^^ help: consider using: `x.exp2()` | - = note: `-D clippy::floating-point-improvements` implied by `-D warnings` + = note: `-D clippy::suboptimal-flops` implied by `-D warnings` error: exponent for bases 2 and e can be computed more accurately --> $DIR/floating_point_powf.rs:6:13 @@ -61,61 +61,61 @@ LL | let _ = x.powf(-2.0); | ^^^^^^^^^^^^ help: consider using: `x.powi(-2)` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:21:13 + --> $DIR/floating_point_powf.rs:19:13 | LL | let _ = 2f64.powf(x); | ^^^^^^^^^^^^ help: consider using: `x.exp2()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:22:13 + --> $DIR/floating_point_powf.rs:20:13 | LL | let _ = 2f64.powf(3.1); | ^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp2()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:23:13 + --> $DIR/floating_point_powf.rs:21:13 | LL | let _ = 2f64.powf(-3.1); | ^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp2()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:24:13 + --> $DIR/floating_point_powf.rs:22:13 | LL | let _ = std::f64::consts::E.powf(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:25:13 + --> $DIR/floating_point_powf.rs:23:13 | LL | let _ = std::f64::consts::E.powf(3.1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:26:13 + --> $DIR/floating_point_powf.rs:24:13 | LL | let _ = std::f64::consts::E.powf(-3.1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp()` error: square-root of a number can be computed more efficiently and accurately - --> $DIR/floating_point_powf.rs:27:13 + --> $DIR/floating_point_powf.rs:25:13 | LL | let _ = x.powf(1.0 / 2.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()` error: cube-root of a number can be computed more accurately - --> $DIR/floating_point_powf.rs:28:13 + --> $DIR/floating_point_powf.rs:26:13 | LL | let _ = x.powf(1.0 / 3.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` error: exponentiation with integer powers can be computed more efficiently - --> $DIR/floating_point_powf.rs:29:13 + --> $DIR/floating_point_powf.rs:27:13 | LL | let _ = x.powf(2.0); | ^^^^^^^^^^^ help: consider using: `x.powi(2)` error: exponentiation with integer powers can be computed more efficiently - --> $DIR/floating_point_powf.rs:30:13 + --> $DIR/floating_point_powf.rs:28:13 | LL | let _ = x.powf(-2.0); | ^^^^^^^^^^^^ help: consider using: `x.powi(-2)` From bc706e3ba93be678852950fdef8cd10790aadfc4 Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Sat, 22 Feb 2020 20:29:22 -0800 Subject: [PATCH 138/243] Fix `powi` suggestion and add general improvements --- clippy_lints/src/floating_point_arithmetic.rs | 72 +++++++++---------- 1 file changed, 34 insertions(+), 38 deletions(-) diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 61938405d92d..d342afbc12a4 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -11,7 +11,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::f32::consts as f32_consts; use std::f64::consts as f64_consts; -use sugg::Sugg; +use sugg::{format_numeric_literal, Sugg}; use syntax::ast; declare_clippy_lint! { @@ -159,23 +159,23 @@ fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { } } -// Returns an integer if the float constant is a whole number and it -// can be converted to an integer without loss -// TODO: Add a better check to determine whether the float can be -// casted without loss +// Returns an integer if the float constant is a whole number and it can be +// converted to an integer without loss of precision. For now we only check +// ranges [-16777215, 16777216) for type f32 as whole number floats outside +// this range are lossy and ambiguous. #[allow(clippy::cast_possible_truncation)] -fn get_integer_from_float_constant(value: &Constant) -> Option { +fn get_integer_from_float_constant(value: &Constant) -> Option { match value { - F32(num) if (num.trunc() - num).abs() <= std::f32::EPSILON => { - if *num > -16_777_217.0 && *num < 16_777_217.0 { - Some(num.round() as i64) + F32(num) if num.fract() == 0.0 => { + if (-16_777_215.0..16_777_216.0).contains(num) { + Some(num.round() as i32) } else { None } }, - F64(num) if (num.trunc() - num).abs() <= std::f64::EPSILON => { - if *num > -9_007_199_254_740_993.0 && *num < 9_007_199_254_740_993.0 { - Some(num.round() as i64) + F64(num) if num.fract() == 0.0 => { + if (-2_147_483_648.0..2_147_483_648.0).contains(num) { + Some(num.round() as i32) } else { None } @@ -187,15 +187,13 @@ fn get_integer_from_float_constant(value: &Constant) -> Option { fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { // Check receiver if let Some((value, _)) = constant(cx, cx.tables, &args[0]) { - let method; - - if F32(f32_consts::E) == value || F64(f64_consts::E) == value { - method = "exp"; + let method = if F32(f32_consts::E) == value || F64(f64_consts::E) == value { + "exp" } else if F32(2.0) == value || F64(2.0) == value { - method = "exp2"; + "exp2" } else { return; - } + }; span_lint_and_sugg( cx, @@ -210,30 +208,28 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { // Check argument if let Some((value, _)) = constant(cx, cx.tables, &args[1]) { - let help; - let method; - - if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value { - help = "square-root of a number can be computed more efficiently and accurately"; - method = "sqrt"; + let (help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value { + ( + "square-root of a number can be computed more efficiently and accurately", + format!("{}.sqrt()", Sugg::hir(cx, &args[0], "..")) + ) } else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value { - help = "cube-root of a number can be computed more accurately"; - method = "cbrt"; + ( + "cube-root of a number can be computed more accurately", + format!("{}.cbrt()", Sugg::hir(cx, &args[0], "..")) + ) } else if let Some(exponent) = get_integer_from_float_constant(&value) { - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, + ( "exponentiation with integer powers can be computed more efficiently", - "consider using", - format!("{}.powi({})", Sugg::hir(cx, &args[0], ".."), exponent), - Applicability::MachineApplicable, - ); - - return; + format!( + "{}.powi({})", + Sugg::hir(cx, &args[0], ".."), + format_numeric_literal(&exponent.to_string(), None, false) + ) + ) } else { return; - } + }; span_lint_and_sugg( cx, @@ -241,7 +237,7 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { expr.span, help, "consider using", - format!("{}.{}()", Sugg::hir(cx, &args[0], ".."), method), + suggestion, Applicability::MachineApplicable, ); } From 454e505c12d6ca2d3c360e9d33d629c2e5652514 Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Sat, 22 Feb 2020 20:32:13 -0800 Subject: [PATCH 139/243] Run rust-fix on tests --- tests/ui/floating_point_exp.fixed | 18 ++++++++ tests/ui/floating_point_exp.rs | 1 + tests/ui/floating_point_exp.stderr | 8 ++-- tests/ui/floating_point_log.fixed | 58 +++++++++++++++++++++++++ tests/ui/floating_point_log.rs | 3 +- tests/ui/floating_point_log.stderr | 56 ++++++++++++------------ tests/ui/floating_point_powf.fixed | 40 +++++++++++++++++ tests/ui/floating_point_powf.rs | 9 ++++ tests/ui/floating_point_powf.stderr | 66 ++++++++++++++++++++--------- 9 files changed, 205 insertions(+), 54 deletions(-) create mode 100644 tests/ui/floating_point_exp.fixed create mode 100644 tests/ui/floating_point_log.fixed create mode 100644 tests/ui/floating_point_powf.fixed diff --git a/tests/ui/floating_point_exp.fixed b/tests/ui/floating_point_exp.fixed new file mode 100644 index 000000000000..1f534e3705d8 --- /dev/null +++ b/tests/ui/floating_point_exp.fixed @@ -0,0 +1,18 @@ +// run-rustfix +#![warn(clippy::suboptimal_flops)] + +fn main() { + let x = 2f32; + let _ = x.exp_m1(); + let _ = x.exp_m1() + 2.0; + // Cases where the lint shouldn't be applied + let _ = x.exp() - 2.0; + let _ = x.exp() - 1.0 * 2.0; + + let x = 2f64; + let _ = x.exp_m1(); + let _ = x.exp_m1() + 2.0; + // Cases where the lint shouldn't be applied + let _ = x.exp() - 2.0; + let _ = x.exp() - 1.0 * 2.0; +} diff --git a/tests/ui/floating_point_exp.rs b/tests/ui/floating_point_exp.rs index c7fe0d035689..bed8d3121408 100644 --- a/tests/ui/floating_point_exp.rs +++ b/tests/ui/floating_point_exp.rs @@ -1,3 +1,4 @@ +// run-rustfix #![warn(clippy::suboptimal_flops)] fn main() { diff --git a/tests/ui/floating_point_exp.stderr b/tests/ui/floating_point_exp.stderr index 83adca8a46c9..7882b2c24e3a 100644 --- a/tests/ui/floating_point_exp.stderr +++ b/tests/ui/floating_point_exp.stderr @@ -1,5 +1,5 @@ error: (e.pow(x) - 1) can be computed more accurately - --> $DIR/floating_point_exp.rs:5:13 + --> $DIR/floating_point_exp.rs:6:13 | LL | let _ = x.exp() - 1.0; | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` @@ -7,19 +7,19 @@ LL | let _ = x.exp() - 1.0; = note: `-D clippy::suboptimal-flops` implied by `-D warnings` error: (e.pow(x) - 1) can be computed more accurately - --> $DIR/floating_point_exp.rs:6:13 + --> $DIR/floating_point_exp.rs:7:13 | LL | let _ = x.exp() - 1.0 + 2.0; | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` error: (e.pow(x) - 1) can be computed more accurately - --> $DIR/floating_point_exp.rs:12:13 + --> $DIR/floating_point_exp.rs:13:13 | LL | let _ = x.exp() - 1.0; | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` error: (e.pow(x) - 1) can be computed more accurately - --> $DIR/floating_point_exp.rs:13:13 + --> $DIR/floating_point_exp.rs:14:13 | LL | let _ = x.exp() - 1.0 + 2.0; | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` diff --git a/tests/ui/floating_point_log.fixed b/tests/ui/floating_point_log.fixed new file mode 100644 index 000000000000..ead45fc4a9f2 --- /dev/null +++ b/tests/ui/floating_point_log.fixed @@ -0,0 +1,58 @@ +// run-rustfix +#![allow(dead_code, clippy::double_parens)] +#![warn(clippy::suboptimal_flops)] + +const TWO: f32 = 2.0; +const E: f32 = std::f32::consts::E; + +fn check_log_base() { + let x = 1f32; + let _ = x.log2(); + let _ = x.log10(); + let _ = x.ln(); + let _ = x.log2(); + let _ = x.ln(); + + let x = 1f64; + let _ = x.log2(); + let _ = x.log10(); + let _ = x.ln(); +} + +fn check_ln1p() { + let x = 1f32; + let _ = 2.0f32.ln_1p(); + let _ = 2.0f32.ln_1p(); + let _ = x.ln_1p(); + let _ = (x * 2.0).ln_1p(); + let _ = x.powi(2).ln_1p(); + let _ = (x.powi(2) * 2.0).ln_1p(); + let _ = ((std::f32::consts::E - 1.0)).ln_1p(); + let _ = x.ln_1p(); + let _ = x.powi(2).ln_1p(); + let _ = (x + 2.0).ln_1p(); + let _ = (x * 2.0).ln_1p(); + // Cases where the lint shouldn't be applied + let _ = (1.0 + x + 2.0).ln(); + let _ = (x + 1.0 + 2.0).ln(); + let _ = (x + 1.0 * 2.0).ln(); + let _ = (1.0 + x - 2.0).ln(); + + let x = 1f64; + let _ = 2.0f64.ln_1p(); + let _ = 2.0f64.ln_1p(); + let _ = x.ln_1p(); + let _ = (x * 2.0).ln_1p(); + let _ = x.powi(2).ln_1p(); + let _ = x.ln_1p(); + let _ = x.powi(2).ln_1p(); + let _ = (x + 2.0).ln_1p(); + let _ = (x * 2.0).ln_1p(); + // Cases where the lint shouldn't be applied + let _ = (1.0 + x + 2.0).ln(); + let _ = (x + 1.0 + 2.0).ln(); + let _ = (x + 1.0 * 2.0).ln(); + let _ = (1.0 + x - 2.0).ln(); +} + +fn main() {} diff --git a/tests/ui/floating_point_log.rs b/tests/ui/floating_point_log.rs index c26f71f3067d..f888e1375dcf 100644 --- a/tests/ui/floating_point_log.rs +++ b/tests/ui/floating_point_log.rs @@ -1,4 +1,5 @@ -#![allow(dead_code)] +// run-rustfix +#![allow(dead_code, clippy::double_parens)] #![warn(clippy::suboptimal_flops)] const TWO: f32 = 2.0; diff --git a/tests/ui/floating_point_log.stderr b/tests/ui/floating_point_log.stderr index db2fc999b6c3..c8c32b61ca36 100644 --- a/tests/ui/floating_point_log.stderr +++ b/tests/ui/floating_point_log.stderr @@ -1,5 +1,5 @@ error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_log.rs:9:13 + --> $DIR/floating_point_log.rs:10:13 | LL | let _ = x.log(2f32); | ^^^^^^^^^^^ help: consider using: `x.log2()` @@ -7,163 +7,163 @@ LL | let _ = x.log(2f32); = note: `-D clippy::suboptimal-flops` implied by `-D warnings` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_log.rs:10:13 + --> $DIR/floating_point_log.rs:11:13 | LL | let _ = x.log(10f32); | ^^^^^^^^^^^^ help: consider using: `x.log10()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_log.rs:11:13 + --> $DIR/floating_point_log.rs:12:13 | LL | let _ = x.log(std::f32::consts::E); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.ln()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_log.rs:12:13 + --> $DIR/floating_point_log.rs:13:13 | LL | let _ = x.log(TWO); | ^^^^^^^^^^ help: consider using: `x.log2()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_log.rs:13:13 + --> $DIR/floating_point_log.rs:14:13 | LL | let _ = x.log(E); | ^^^^^^^^ help: consider using: `x.ln()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_log.rs:16:13 + --> $DIR/floating_point_log.rs:17:13 | LL | let _ = x.log(2f64); | ^^^^^^^^^^^ help: consider using: `x.log2()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_log.rs:17:13 + --> $DIR/floating_point_log.rs:18:13 | LL | let _ = x.log(10f64); | ^^^^^^^^^^^^ help: consider using: `x.log10()` error: logarithm for bases 2, 10 and e can be computed more accurately - --> $DIR/floating_point_log.rs:18:13 + --> $DIR/floating_point_log.rs:19:13 | LL | let _ = x.log(std::f64::consts::E); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.ln()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:23:13 + --> $DIR/floating_point_log.rs:24:13 | LL | let _ = (1f32 + 2.).ln(); | ^^^^^^^^^^^^^^^^ help: consider using: `2.0f32.ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:24:13 + --> $DIR/floating_point_log.rs:25:13 | LL | let _ = (1f32 + 2.0).ln(); | ^^^^^^^^^^^^^^^^^ help: consider using: `2.0f32.ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:25:13 + --> $DIR/floating_point_log.rs:26:13 | LL | let _ = (1.0 + x).ln(); | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:26:13 + --> $DIR/floating_point_log.rs:27:13 | LL | let _ = (1.0 + x * 2.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:27:13 + --> $DIR/floating_point_log.rs:28:13 | LL | let _ = (1.0 + x.powi(2)).ln(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:28:13 + --> $DIR/floating_point_log.rs:29:13 | LL | let _ = (1.0 + x.powi(2) * 2.0).ln(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x.powi(2) * 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:29:13 + --> $DIR/floating_point_log.rs:30:13 | LL | let _ = (1.0 + (std::f32::consts::E - 1.0)).ln(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `((std::f32::consts::E - 1.0)).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:30:13 + --> $DIR/floating_point_log.rs:31:13 | LL | let _ = (x + 1.0).ln(); | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:31:13 + --> $DIR/floating_point_log.rs:32:13 | LL | let _ = (x.powi(2) + 1.0).ln(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:32:13 + --> $DIR/floating_point_log.rs:33:13 | LL | let _ = (x + 2.0 + 1.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x + 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:33:13 + --> $DIR/floating_point_log.rs:34:13 | LL | let _ = (x * 2.0 + 1.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:41:13 + --> $DIR/floating_point_log.rs:42:13 | LL | let _ = (1f64 + 2.).ln(); | ^^^^^^^^^^^^^^^^ help: consider using: `2.0f64.ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:42:13 + --> $DIR/floating_point_log.rs:43:13 | LL | let _ = (1f64 + 2.0).ln(); | ^^^^^^^^^^^^^^^^^ help: consider using: `2.0f64.ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:43:13 + --> $DIR/floating_point_log.rs:44:13 | LL | let _ = (1.0 + x).ln(); | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:44:13 + --> $DIR/floating_point_log.rs:45:13 | LL | let _ = (1.0 + x * 2.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:45:13 + --> $DIR/floating_point_log.rs:46:13 | LL | let _ = (1.0 + x.powi(2)).ln(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:46:13 + --> $DIR/floating_point_log.rs:47:13 | LL | let _ = (x + 1.0).ln(); | ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:47:13 + --> $DIR/floating_point_log.rs:48:13 | LL | let _ = (x.powi(2) + 1.0).ln(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:48:13 + --> $DIR/floating_point_log.rs:49:13 | LL | let _ = (x + 2.0 + 1.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x + 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately - --> $DIR/floating_point_log.rs:49:13 + --> $DIR/floating_point_log.rs:50:13 | LL | let _ = (x * 2.0 + 1.0).ln(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` diff --git a/tests/ui/floating_point_powf.fixed b/tests/ui/floating_point_powf.fixed new file mode 100644 index 000000000000..54d130a22beb --- /dev/null +++ b/tests/ui/floating_point_powf.fixed @@ -0,0 +1,40 @@ +// run-rustfix +#![warn(clippy::suboptimal_flops)] + +fn main() { + let x = 3f32; + let _ = x.exp2(); + let _ = 3.1f32.exp2(); + let _ = (-3.1f32).exp2(); + let _ = x.exp(); + let _ = 3.1f32.exp(); + let _ = (-3.1f32).exp(); + let _ = x.sqrt(); + let _ = x.cbrt(); + let _ = x.powi(2); + let _ = x.powi(-2); + let _ = x.powi(16_777_215); + let _ = x.powi(-16_777_215); + let _ = x.powf(2.1); + let _ = x.powf(-2.1); + let _ = x.powf(16_777_216.0); + let _ = x.powf(-16_777_216.0); + + let x = 3f64; + let _ = x.exp2(); + let _ = 3.1f64.exp2(); + let _ = (-3.1f64).exp2(); + let _ = x.exp(); + let _ = 3.1f64.exp(); + let _ = (-3.1f64).exp(); + let _ = x.sqrt(); + let _ = x.cbrt(); + let _ = x.powi(2); + let _ = x.powi(-2); + let _ = x.powi(-2_147_483_648); + let _ = x.powi(2_147_483_647); + let _ = x.powf(2.1); + let _ = x.powf(-2.1); + let _ = x.powf(-2_147_483_649.0); + let _ = x.powf(2_147_483_648.0); +} diff --git a/tests/ui/floating_point_powf.rs b/tests/ui/floating_point_powf.rs index 2076821b5b04..c1b64d704cd6 100644 --- a/tests/ui/floating_point_powf.rs +++ b/tests/ui/floating_point_powf.rs @@ -1,3 +1,4 @@ +// run-rustfix #![warn(clippy::suboptimal_flops)] fn main() { @@ -12,8 +13,12 @@ fn main() { let _ = x.powf(1.0 / 3.0); let _ = x.powf(2.0); let _ = x.powf(-2.0); + let _ = x.powf(16_777_215.0); + let _ = x.powf(-16_777_215.0); let _ = x.powf(2.1); let _ = x.powf(-2.1); + let _ = x.powf(16_777_216.0); + let _ = x.powf(-16_777_216.0); let x = 3f64; let _ = 2f64.powf(x); @@ -26,6 +31,10 @@ fn main() { let _ = x.powf(1.0 / 3.0); let _ = x.powf(2.0); let _ = x.powf(-2.0); + let _ = x.powf(-2_147_483_648.0); + let _ = x.powf(2_147_483_647.0); let _ = x.powf(2.1); let _ = x.powf(-2.1); + let _ = x.powf(-2_147_483_649.0); + let _ = x.powf(2_147_483_648.0); } diff --git a/tests/ui/floating_point_powf.stderr b/tests/ui/floating_point_powf.stderr index 35e0c5e56fd8..2b912c5940ed 100644 --- a/tests/ui/floating_point_powf.stderr +++ b/tests/ui/floating_point_powf.stderr @@ -1,5 +1,5 @@ error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:5:13 + --> $DIR/floating_point_powf.rs:6:13 | LL | let _ = 2f32.powf(x); | ^^^^^^^^^^^^ help: consider using: `x.exp2()` @@ -7,118 +7,142 @@ LL | let _ = 2f32.powf(x); = note: `-D clippy::suboptimal-flops` implied by `-D warnings` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:6:13 + --> $DIR/floating_point_powf.rs:7:13 | LL | let _ = 2f32.powf(3.1); | ^^^^^^^^^^^^^^ help: consider using: `3.1f32.exp2()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:7:13 + --> $DIR/floating_point_powf.rs:8:13 | LL | let _ = 2f32.powf(-3.1); | ^^^^^^^^^^^^^^^ help: consider using: `(-3.1f32).exp2()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:8:13 + --> $DIR/floating_point_powf.rs:9:13 | LL | let _ = std::f32::consts::E.powf(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:9:13 + --> $DIR/floating_point_powf.rs:10:13 | LL | let _ = std::f32::consts::E.powf(3.1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `3.1f32.exp()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:10:13 + --> $DIR/floating_point_powf.rs:11:13 | LL | let _ = std::f32::consts::E.powf(-3.1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-3.1f32).exp()` error: square-root of a number can be computed more efficiently and accurately - --> $DIR/floating_point_powf.rs:11:13 + --> $DIR/floating_point_powf.rs:12:13 | LL | let _ = x.powf(1.0 / 2.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()` error: cube-root of a number can be computed more accurately - --> $DIR/floating_point_powf.rs:12:13 + --> $DIR/floating_point_powf.rs:13:13 | LL | let _ = x.powf(1.0 / 3.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` error: exponentiation with integer powers can be computed more efficiently - --> $DIR/floating_point_powf.rs:13:13 + --> $DIR/floating_point_powf.rs:14:13 | LL | let _ = x.powf(2.0); | ^^^^^^^^^^^ help: consider using: `x.powi(2)` error: exponentiation with integer powers can be computed more efficiently - --> $DIR/floating_point_powf.rs:14:13 + --> $DIR/floating_point_powf.rs:15:13 | LL | let _ = x.powf(-2.0); | ^^^^^^^^^^^^ help: consider using: `x.powi(-2)` +error: exponentiation with integer powers can be computed more efficiently + --> $DIR/floating_point_powf.rs:16:13 + | +LL | let _ = x.powf(16_777_215.0); + | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(16_777_215)` + +error: exponentiation with integer powers can be computed more efficiently + --> $DIR/floating_point_powf.rs:17:13 + | +LL | let _ = x.powf(-16_777_215.0); + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(-16_777_215)` + error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:19:13 + --> $DIR/floating_point_powf.rs:24:13 | LL | let _ = 2f64.powf(x); | ^^^^^^^^^^^^ help: consider using: `x.exp2()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:20:13 + --> $DIR/floating_point_powf.rs:25:13 | LL | let _ = 2f64.powf(3.1); | ^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp2()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:21:13 + --> $DIR/floating_point_powf.rs:26:13 | LL | let _ = 2f64.powf(-3.1); | ^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp2()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:22:13 + --> $DIR/floating_point_powf.rs:27:13 | LL | let _ = std::f64::consts::E.powf(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:23:13 + --> $DIR/floating_point_powf.rs:28:13 | LL | let _ = std::f64::consts::E.powf(3.1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:24:13 + --> $DIR/floating_point_powf.rs:29:13 | LL | let _ = std::f64::consts::E.powf(-3.1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp()` error: square-root of a number can be computed more efficiently and accurately - --> $DIR/floating_point_powf.rs:25:13 + --> $DIR/floating_point_powf.rs:30:13 | LL | let _ = x.powf(1.0 / 2.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()` error: cube-root of a number can be computed more accurately - --> $DIR/floating_point_powf.rs:26:13 + --> $DIR/floating_point_powf.rs:31:13 | LL | let _ = x.powf(1.0 / 3.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` error: exponentiation with integer powers can be computed more efficiently - --> $DIR/floating_point_powf.rs:27:13 + --> $DIR/floating_point_powf.rs:32:13 | LL | let _ = x.powf(2.0); | ^^^^^^^^^^^ help: consider using: `x.powi(2)` error: exponentiation with integer powers can be computed more efficiently - --> $DIR/floating_point_powf.rs:28:13 + --> $DIR/floating_point_powf.rs:33:13 | LL | let _ = x.powf(-2.0); | ^^^^^^^^^^^^ help: consider using: `x.powi(-2)` -error: aborting due to 20 previous errors +error: exponentiation with integer powers can be computed more efficiently + --> $DIR/floating_point_powf.rs:34:13 + | +LL | let _ = x.powf(-2_147_483_648.0); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(-2_147_483_648)` + +error: exponentiation with integer powers can be computed more efficiently + --> $DIR/floating_point_powf.rs:35:13 + | +LL | let _ = x.powf(2_147_483_647.0); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2_147_483_647)` + +error: aborting due to 24 previous errors From 4065ca9c8c4586e99688de53c7cf654c7693fc63 Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Sun, 23 Feb 2020 00:04:11 -0800 Subject: [PATCH 140/243] Move `manual_mul_add` into `suboptimal_flops` lint --- CHANGELOG.md | 1 - clippy_lints/src/floating_point_arithmetic.rs | 59 +++++++++- clippy_lints/src/lib.rs | 5 +- clippy_lints/src/mul_add.rs | 111 ------------------ src/lintlist/mod.rs | 7 -- tests/ui/floating_point_fma.fixed | 21 ++++ tests/ui/floating_point_fma.rs | 21 ++++ tests/ui/floating_point_fma.stderr | 58 +++++++++ tests/ui/floating_point_log.fixed | 14 +-- tests/ui/floating_point_log.rs | 14 +-- tests/ui/floating_point_log.stderr | 20 ++-- tests/ui/mul_add.rs | 16 --- tests/ui/mul_add.stderr | 34 ------ tests/ui/mul_add_fixable.fixed | 24 ---- tests/ui/mul_add_fixable.rs | 24 ---- tests/ui/mul_add_fixable.stderr | 40 ------- 16 files changed, 179 insertions(+), 290 deletions(-) delete mode 100644 clippy_lints/src/mul_add.rs create mode 100644 tests/ui/floating_point_fma.fixed create mode 100644 tests/ui/floating_point_fma.rs create mode 100644 tests/ui/floating_point_fma.stderr delete mode 100644 tests/ui/mul_add.rs delete mode 100644 tests/ui/mul_add.stderr delete mode 100644 tests/ui/mul_add_fixable.fixed delete mode 100644 tests/ui/mul_add_fixable.rs delete mode 100644 tests/ui/mul_add_fixable.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 87ece835f7f0..ce696aa85501 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1210,7 +1210,6 @@ Released 2018-09-13 [`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal [`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion [`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy -[`manual_mul_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_mul_add [`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic [`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap [`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index d342afbc12a4..fbc375c655e6 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -2,11 +2,11 @@ use crate::consts::{ constant, Constant, Constant::{F32, F64}, }; -use crate::utils::*; +use crate::utils::{span_lint_and_sugg, sugg}; use if_chain::if_chain; use rustc::ty; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::f32::consts as f32_consts; @@ -39,6 +39,7 @@ declare_clippy_lint! { /// let _ = (1.0 + a).ln(); /// let _ = a.exp() - 1.0; /// let _ = a.powf(2.0); + /// let _ = a * 2.0 + 4.0; /// ``` /// /// is better expressed as @@ -57,6 +58,7 @@ declare_clippy_lint! { /// let _ = a.ln_1p(); /// let _ = a.exp_m1(); /// let _ = a.powi(2); + /// let _ = a.mul_add(2.0, 4.0); /// ``` pub SUBOPTIMAL_FLOPS, nursery, @@ -211,12 +213,12 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { let (help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value { ( "square-root of a number can be computed more efficiently and accurately", - format!("{}.sqrt()", Sugg::hir(cx, &args[0], "..")) + format!("{}.sqrt()", Sugg::hir(cx, &args[0], "..")), ) } else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value { ( "cube-root of a number can be computed more accurately", - format!("{}.cbrt()", Sugg::hir(cx, &args[0], "..")) + format!("{}.cbrt()", Sugg::hir(cx, &args[0], "..")), ) } else if let Some(exponent) = get_integer_from_float_constant(&value) { ( @@ -225,7 +227,7 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { "{}.powi({})", Sugg::hir(cx, &args[0], ".."), format_numeric_literal(&exponent.to_string(), None, false) - ) + ), ) } else { return; @@ -272,6 +274,52 @@ fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { } } +fn is_float_mul_expr<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> { + if_chain! { + if let ExprKind::Binary(op, ref lhs, ref rhs) = &expr.kind; + if let BinOpKind::Mul = op.node; + if cx.tables.expr_ty(lhs).is_floating_point(); + if cx.tables.expr_ty(rhs).is_floating_point(); + then { + return Some((lhs, rhs)); + } + } + + None +} + +// TODO: Fix rust-lang/rust-clippy#4735 +fn check_fma(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { + if_chain! { + if let ExprKind::Binary(op, lhs, rhs) = &expr.kind; + if let BinOpKind::Add = op.node; + then { + let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) { + (inner_lhs, inner_rhs, rhs) + } else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) { + (inner_lhs, inner_rhs, lhs) + } else { + return; + }; + + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "multiply and add expressions can be calculated more efficiently and accurately", + "consider using", + format!( + "{}.mul_add({}, {})", + prepare_receiver_sugg(cx, recv), + Sugg::hir(cx, arg1, ".."), + Sugg::hir(cx, arg2, ".."), + ), + Applicability::MachineApplicable, + ); + } + } +} + impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::MethodCall(ref path, _, args) = &expr.kind { @@ -287,6 +335,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic { } } else { check_expm1(cx, expr); + check_fma(cx, expr); } } } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 59ad7e7a651a..503eb9ec10d6 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -208,6 +208,7 @@ pub mod exit; pub mod explicit_write; pub mod fallible_impl_from; pub mod float_literal; +pub mod floating_point_arithmetic; pub mod format; pub mod formatting; pub mod functions; @@ -248,7 +249,6 @@ pub mod missing_const_for_fn; pub mod missing_doc; pub mod missing_inline; pub mod modulo_arithmetic; -pub mod mul_add; pub mod multiple_crate_versions; pub mod mut_key; pub mod mut_mut; @@ -691,7 +691,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS, &missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS, &modulo_arithmetic::MODULO_ARITHMETIC, - &mul_add::MANUAL_MUL_ADD, &multiple_crate_versions::MULTIPLE_CRATE_VERSIONS, &mut_key::MUTABLE_KEY_TYPE, &mut_mut::MUT_MUT, @@ -967,7 +966,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box inherent_to_string::InherentToString); store.register_late_pass(|| box trait_bounds::TraitBounds); store.register_late_pass(|| box comparison_chain::ComparisonChain); - store.register_late_pass(|| box mul_add::MulAddCheck); store.register_late_pass(|| box mut_key::MutableKeyType); store.register_late_pass(|| box modulo_arithmetic::ModuloArithmetic); store.register_early_pass(|| box reference::DerefAddrOf); @@ -1652,7 +1650,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&fallible_impl_from::FALLIBLE_IMPL_FROM), LintId::of(&floating_point_arithmetic::SUBOPTIMAL_FLOPS), LintId::of(&missing_const_for_fn::MISSING_CONST_FOR_FN), - LintId::of(&mul_add::MANUAL_MUL_ADD), LintId::of(&mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL), LintId::of(&mutex_atomic::MUTEX_INTEGER), LintId::of(&needless_borrow::NEEDLESS_BORROW), diff --git a/clippy_lints/src/mul_add.rs b/clippy_lints/src/mul_add.rs deleted file mode 100644 index 57e56d8f959a..000000000000 --- a/clippy_lints/src/mul_add.rs +++ /dev/null @@ -1,111 +0,0 @@ -use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; - -use crate::utils::{snippet, span_lint_and_sugg}; - -declare_clippy_lint! { - /// **What it does:** Checks for expressions of the form `a * b + c` - /// or `c + a * b` where `a`, `b`, `c` are floats and suggests using - /// `a.mul_add(b, c)` instead. - /// - /// **Why is this bad?** Calculating `a * b + c` may lead to slight - /// numerical inaccuracies as `a * b` is rounded before being added to - /// `c`. Depending on the target architecture, `mul_add()` may be more - /// performant. - /// - /// **Known problems:** This lint can emit semantic incorrect suggestions. - /// For example, for `a * b * c + d` the suggestion `a * b.mul_add(c, d)` - /// is emitted, which is equivalent to `a * (b * c + d)`. (#4735) - /// - /// **Example:** - /// - /// ```rust - /// # let a = 0_f32; - /// # let b = 0_f32; - /// # let c = 0_f32; - /// let foo = (a * b) + c; - /// ``` - /// - /// can be written as - /// - /// ```rust - /// # let a = 0_f32; - /// # let b = 0_f32; - /// # let c = 0_f32; - /// let foo = a.mul_add(b, c); - /// ``` - pub MANUAL_MUL_ADD, - nursery, - "Using `a.mul_add(b, c)` for floating points has higher numerical precision than `a * b + c`" -} - -declare_lint_pass!(MulAddCheck => [MANUAL_MUL_ADD]); - -fn is_float<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>) -> bool { - cx.tables.expr_ty(expr).is_floating_point() -} - -// Checks whether expression is multiplication of two floats -fn is_float_mult_expr<'a, 'tcx, 'b>( - cx: &LateContext<'a, 'tcx>, - expr: &'b Expr<'b>, -) -> Option<(&'b Expr<'b>, &'b Expr<'b>)> { - if let ExprKind::Binary(op, lhs, rhs) = &expr.kind { - if let BinOpKind::Mul = op.node { - if is_float(cx, &lhs) && is_float(cx, &rhs) { - return Some((&lhs, &rhs)); - } - } - } - - None -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MulAddCheck { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Binary(op, lhs, rhs) = &expr.kind { - if let BinOpKind::Add = op.node { - //Converts mult_lhs * mult_rhs + rhs to mult_lhs.mult_add(mult_rhs, rhs) - if let Some((mult_lhs, mult_rhs)) = is_float_mult_expr(cx, lhs) { - if is_float(cx, rhs) { - span_lint_and_sugg( - cx, - MANUAL_MUL_ADD, - expr.span, - "consider using `mul_add()` for better numerical precision", - "try", - format!( - "{}.mul_add({}, {})", - snippet(cx, mult_lhs.span, "_"), - snippet(cx, mult_rhs.span, "_"), - snippet(cx, rhs.span, "_"), - ), - Applicability::MaybeIncorrect, - ); - } - } - //Converts lhs + mult_lhs * mult_rhs to mult_lhs.mult_add(mult_rhs, lhs) - if let Some((mult_lhs, mult_rhs)) = is_float_mult_expr(cx, rhs) { - if is_float(cx, lhs) { - span_lint_and_sugg( - cx, - MANUAL_MUL_ADD, - expr.span, - "consider using `mul_add()` for better numerical precision", - "try", - format!( - "{}.mul_add({}, {})", - snippet(cx, mult_lhs.span, "_"), - snippet(cx, mult_rhs.span, "_"), - snippet(cx, lhs.span, "_"), - ), - Applicability::MaybeIncorrect, - ); - } - } - } - } - } -} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index de086f863e01..5b4aad347af2 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1022,13 +1022,6 @@ pub const ALL_LINTS: [Lint; 357] = [ deprecation: None, module: "loops", }, - Lint { - name: "manual_mul_add", - group: "nursery", - desc: "Using `a.mul_add(b, c)` for floating points has higher numerical precision than `a * b + c`", - deprecation: None, - module: "mul_add", - }, Lint { name: "manual_saturating_arithmetic", group: "style", diff --git a/tests/ui/floating_point_fma.fixed b/tests/ui/floating_point_fma.fixed new file mode 100644 index 000000000000..e343c37740da --- /dev/null +++ b/tests/ui/floating_point_fma.fixed @@ -0,0 +1,21 @@ +// run-rustfix +#![warn(clippy::suboptimal_flops)] + +fn main() { + let a: f64 = 1234.567; + let b: f64 = 45.67834; + let c: f64 = 0.0004; + let d: f64 = 0.0001; + + let _ = a.mul_add(b, c); + let _ = a.mul_add(b, c); + let _ = 2.0f64.mul_add(4.0, a); + let _ = 2.0f64.mul_add(4., a); + + let _ = a.mul_add(b, c); + let _ = a.mul_add(b, c); + let _ = (a * b).mul_add(c, d); + + let _ = a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c)) + c; + let _ = 1234.567_f64.mul_add(45.67834_f64, 0.0004_f64); +} diff --git a/tests/ui/floating_point_fma.rs b/tests/ui/floating_point_fma.rs new file mode 100644 index 000000000000..810f929c8568 --- /dev/null +++ b/tests/ui/floating_point_fma.rs @@ -0,0 +1,21 @@ +// run-rustfix +#![warn(clippy::suboptimal_flops)] + +fn main() { + let a: f64 = 1234.567; + let b: f64 = 45.67834; + let c: f64 = 0.0004; + let d: f64 = 0.0001; + + let _ = a * b + c; + let _ = c + a * b; + let _ = a + 2.0 * 4.0; + let _ = a + 2. * 4.; + + let _ = (a * b) + c; + let _ = c + (a * b); + let _ = a * b * c + d; + + let _ = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c; + let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64; +} diff --git a/tests/ui/floating_point_fma.stderr b/tests/ui/floating_point_fma.stderr new file mode 100644 index 000000000000..5c653360ebc8 --- /dev/null +++ b/tests/ui/floating_point_fma.stderr @@ -0,0 +1,58 @@ +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_fma.rs:10:13 + | +LL | let _ = a * b + c; + | ^^^^^^^^^ help: consider using: `a.mul_add(b, c)` + | + = note: `-D clippy::suboptimal-flops` implied by `-D warnings` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_fma.rs:11:13 + | +LL | let _ = c + a * b; + | ^^^^^^^^^ help: consider using: `a.mul_add(b, c)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_fma.rs:12:13 + | +LL | let _ = a + 2.0 * 4.0; + | ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4.0, a)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_fma.rs:13:13 + | +LL | let _ = a + 2. * 4.; + | ^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4., a)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_fma.rs:15:13 + | +LL | let _ = (a * b) + c; + | ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_fma.rs:16:13 + | +LL | let _ = c + (a * b); + | ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_fma.rs:17:13 + | +LL | let _ = a * b * c + d; + | ^^^^^^^^^^^^^ help: consider using: `(a * b).mul_add(c, d)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_fma.rs:19:13 + | +LL | let _ = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c))` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_fma.rs:20:13 + | +LL | let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1234.567_f64.mul_add(45.67834_f64, 0.0004_f64)` + +error: aborting due to 9 previous errors + diff --git a/tests/ui/floating_point_log.fixed b/tests/ui/floating_point_log.fixed index ead45fc4a9f2..afe72a8dd110 100644 --- a/tests/ui/floating_point_log.fixed +++ b/tests/ui/floating_point_log.fixed @@ -24,34 +24,34 @@ fn check_ln1p() { let _ = 2.0f32.ln_1p(); let _ = 2.0f32.ln_1p(); let _ = x.ln_1p(); - let _ = (x * 2.0).ln_1p(); + let _ = (x / 2.0).ln_1p(); let _ = x.powi(2).ln_1p(); - let _ = (x.powi(2) * 2.0).ln_1p(); + let _ = (x.powi(2) / 2.0).ln_1p(); let _ = ((std::f32::consts::E - 1.0)).ln_1p(); let _ = x.ln_1p(); let _ = x.powi(2).ln_1p(); let _ = (x + 2.0).ln_1p(); - let _ = (x * 2.0).ln_1p(); + let _ = (x / 2.0).ln_1p(); // Cases where the lint shouldn't be applied let _ = (1.0 + x + 2.0).ln(); let _ = (x + 1.0 + 2.0).ln(); - let _ = (x + 1.0 * 2.0).ln(); + let _ = (x + 1.0 / 2.0).ln(); let _ = (1.0 + x - 2.0).ln(); let x = 1f64; let _ = 2.0f64.ln_1p(); let _ = 2.0f64.ln_1p(); let _ = x.ln_1p(); - let _ = (x * 2.0).ln_1p(); + let _ = (x / 2.0).ln_1p(); let _ = x.powi(2).ln_1p(); let _ = x.ln_1p(); let _ = x.powi(2).ln_1p(); let _ = (x + 2.0).ln_1p(); - let _ = (x * 2.0).ln_1p(); + let _ = (x / 2.0).ln_1p(); // Cases where the lint shouldn't be applied let _ = (1.0 + x + 2.0).ln(); let _ = (x + 1.0 + 2.0).ln(); - let _ = (x + 1.0 * 2.0).ln(); + let _ = (x + 1.0 / 2.0).ln(); let _ = (1.0 + x - 2.0).ln(); } diff --git a/tests/ui/floating_point_log.rs b/tests/ui/floating_point_log.rs index f888e1375dcf..785b5a3bc487 100644 --- a/tests/ui/floating_point_log.rs +++ b/tests/ui/floating_point_log.rs @@ -24,34 +24,34 @@ fn check_ln1p() { let _ = (1f32 + 2.).ln(); let _ = (1f32 + 2.0).ln(); let _ = (1.0 + x).ln(); - let _ = (1.0 + x * 2.0).ln(); + let _ = (1.0 + x / 2.0).ln(); let _ = (1.0 + x.powi(2)).ln(); - let _ = (1.0 + x.powi(2) * 2.0).ln(); + let _ = (1.0 + x.powi(2) / 2.0).ln(); let _ = (1.0 + (std::f32::consts::E - 1.0)).ln(); let _ = (x + 1.0).ln(); let _ = (x.powi(2) + 1.0).ln(); let _ = (x + 2.0 + 1.0).ln(); - let _ = (x * 2.0 + 1.0).ln(); + let _ = (x / 2.0 + 1.0).ln(); // Cases where the lint shouldn't be applied let _ = (1.0 + x + 2.0).ln(); let _ = (x + 1.0 + 2.0).ln(); - let _ = (x + 1.0 * 2.0).ln(); + let _ = (x + 1.0 / 2.0).ln(); let _ = (1.0 + x - 2.0).ln(); let x = 1f64; let _ = (1f64 + 2.).ln(); let _ = (1f64 + 2.0).ln(); let _ = (1.0 + x).ln(); - let _ = (1.0 + x * 2.0).ln(); + let _ = (1.0 + x / 2.0).ln(); let _ = (1.0 + x.powi(2)).ln(); let _ = (x + 1.0).ln(); let _ = (x.powi(2) + 1.0).ln(); let _ = (x + 2.0 + 1.0).ln(); - let _ = (x * 2.0 + 1.0).ln(); + let _ = (x / 2.0 + 1.0).ln(); // Cases where the lint shouldn't be applied let _ = (1.0 + x + 2.0).ln(); let _ = (x + 1.0 + 2.0).ln(); - let _ = (x + 1.0 * 2.0).ln(); + let _ = (x + 1.0 / 2.0).ln(); let _ = (1.0 + x - 2.0).ln(); } diff --git a/tests/ui/floating_point_log.stderr b/tests/ui/floating_point_log.stderr index c8c32b61ca36..cb0bb6d652a8 100644 --- a/tests/ui/floating_point_log.stderr +++ b/tests/ui/floating_point_log.stderr @@ -69,8 +69,8 @@ LL | let _ = (1.0 + x).ln(); error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:27:13 | -LL | let _ = (1.0 + x * 2.0).ln(); - | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` +LL | let _ = (1.0 + x / 2.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x / 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:28:13 @@ -81,8 +81,8 @@ LL | let _ = (1.0 + x.powi(2)).ln(); error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:29:13 | -LL | let _ = (1.0 + x.powi(2) * 2.0).ln(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x.powi(2) * 2.0).ln_1p()` +LL | let _ = (1.0 + x.powi(2) / 2.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x.powi(2) / 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:30:13 @@ -111,8 +111,8 @@ LL | let _ = (x + 2.0 + 1.0).ln(); error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:34:13 | -LL | let _ = (x * 2.0 + 1.0).ln(); - | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` +LL | let _ = (x / 2.0 + 1.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x / 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:42:13 @@ -135,8 +135,8 @@ LL | let _ = (1.0 + x).ln(); error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:45:13 | -LL | let _ = (1.0 + x * 2.0).ln(); - | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` +LL | let _ = (1.0 + x / 2.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x / 2.0).ln_1p()` error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:46:13 @@ -165,8 +165,8 @@ LL | let _ = (x + 2.0 + 1.0).ln(); error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:50:13 | -LL | let _ = (x * 2.0 + 1.0).ln(); - | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()` +LL | let _ = (x / 2.0 + 1.0).ln(); + | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x / 2.0).ln_1p()` error: aborting due to 28 previous errors diff --git a/tests/ui/mul_add.rs b/tests/ui/mul_add.rs deleted file mode 100644 index 1322e002c641..000000000000 --- a/tests/ui/mul_add.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![warn(clippy::manual_mul_add)] -#![allow(unused_variables)] - -fn mul_add_test() { - let a: f64 = 1234.567; - let b: f64 = 45.67834; - let c: f64 = 0.0004; - - // Examples of not auto-fixable expressions - let test1 = (a * b + c) * (c + a * b) + (c + (a * b) + c); - let test2 = 1234.567 * 45.67834 + 0.0004; -} - -fn main() { - mul_add_test(); -} diff --git a/tests/ui/mul_add.stderr b/tests/ui/mul_add.stderr deleted file mode 100644 index 3b21646f7c30..000000000000 --- a/tests/ui/mul_add.stderr +++ /dev/null @@ -1,34 +0,0 @@ -error: consider using `mul_add()` for better numerical precision - --> $DIR/mul_add.rs:10:17 - | -LL | let test1 = (a * b + c) * (c + a * b) + (c + (a * b) + c); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(a * b + c).mul_add((c + a * b), (c + (a * b) + c))` - | - = note: `-D clippy::manual-mul-add` implied by `-D warnings` - -error: consider using `mul_add()` for better numerical precision - --> $DIR/mul_add.rs:10:17 - | -LL | let test1 = (a * b + c) * (c + a * b) + (c + (a * b) + c); - | ^^^^^^^^^^^ help: try: `a.mul_add(b, c)` - -error: consider using `mul_add()` for better numerical precision - --> $DIR/mul_add.rs:10:31 - | -LL | let test1 = (a * b + c) * (c + a * b) + (c + (a * b) + c); - | ^^^^^^^^^^^ help: try: `a.mul_add(b, c)` - -error: consider using `mul_add()` for better numerical precision - --> $DIR/mul_add.rs:10:46 - | -LL | let test1 = (a * b + c) * (c + a * b) + (c + (a * b) + c); - | ^^^^^^^^^^^ help: try: `a.mul_add(b, c)` - -error: consider using `mul_add()` for better numerical precision - --> $DIR/mul_add.rs:11:17 - | -LL | let test2 = 1234.567 * 45.67834 + 0.0004; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1234.567.mul_add(45.67834, 0.0004)` - -error: aborting due to 5 previous errors - diff --git a/tests/ui/mul_add_fixable.fixed b/tests/ui/mul_add_fixable.fixed deleted file mode 100644 index 4af7c7e3e1a5..000000000000 --- a/tests/ui/mul_add_fixable.fixed +++ /dev/null @@ -1,24 +0,0 @@ -// run-rustfix - -#![warn(clippy::manual_mul_add)] -#![allow(unused_variables)] - -fn mul_add_test() { - let a: f64 = 1234.567; - let b: f64 = 45.67834; - let c: f64 = 0.0004; - - // Auto-fixable examples - let test1 = a.mul_add(b, c); - let test2 = a.mul_add(b, c); - - let test3 = a.mul_add(b, c); - let test4 = a.mul_add(b, c); - - let test5 = a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c)) + c; - let test6 = 1234.567_f64.mul_add(45.67834_f64, 0.0004_f64); -} - -fn main() { - mul_add_test(); -} diff --git a/tests/ui/mul_add_fixable.rs b/tests/ui/mul_add_fixable.rs deleted file mode 100644 index 8b42f6f184a4..000000000000 --- a/tests/ui/mul_add_fixable.rs +++ /dev/null @@ -1,24 +0,0 @@ -// run-rustfix - -#![warn(clippy::manual_mul_add)] -#![allow(unused_variables)] - -fn mul_add_test() { - let a: f64 = 1234.567; - let b: f64 = 45.67834; - let c: f64 = 0.0004; - - // Auto-fixable examples - let test1 = a * b + c; - let test2 = c + a * b; - - let test3 = (a * b) + c; - let test4 = c + (a * b); - - let test5 = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c; - let test6 = 1234.567_f64 * 45.67834_f64 + 0.0004_f64; -} - -fn main() { - mul_add_test(); -} diff --git a/tests/ui/mul_add_fixable.stderr b/tests/ui/mul_add_fixable.stderr deleted file mode 100644 index 235443f4b02b..000000000000 --- a/tests/ui/mul_add_fixable.stderr +++ /dev/null @@ -1,40 +0,0 @@ -error: consider using `mul_add()` for better numerical precision - --> $DIR/mul_add_fixable.rs:12:17 - | -LL | let test1 = a * b + c; - | ^^^^^^^^^ help: try: `a.mul_add(b, c)` - | - = note: `-D clippy::manual-mul-add` implied by `-D warnings` - -error: consider using `mul_add()` for better numerical precision - --> $DIR/mul_add_fixable.rs:13:17 - | -LL | let test2 = c + a * b; - | ^^^^^^^^^ help: try: `a.mul_add(b, c)` - -error: consider using `mul_add()` for better numerical precision - --> $DIR/mul_add_fixable.rs:15:17 - | -LL | let test3 = (a * b) + c; - | ^^^^^^^^^^^ help: try: `a.mul_add(b, c)` - -error: consider using `mul_add()` for better numerical precision - --> $DIR/mul_add_fixable.rs:16:17 - | -LL | let test4 = c + (a * b); - | ^^^^^^^^^^^ help: try: `a.mul_add(b, c)` - -error: consider using `mul_add()` for better numerical precision - --> $DIR/mul_add_fixable.rs:18:17 - | -LL | let test5 = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c))` - -error: consider using `mul_add()` for better numerical precision - --> $DIR/mul_add_fixable.rs:19:17 - | -LL | let test6 = 1234.567_f64 * 45.67834_f64 + 0.0004_f64; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1234.567_f64.mul_add(45.67834_f64, 0.0004_f64)` - -error: aborting due to 6 previous errors - From e94a167508604d4f4d37bbd654fc3a39056ef99b Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Sun, 23 Feb 2020 20:48:57 -0800 Subject: [PATCH 141/243] Rename `mul_add` test file and add general improvements --- clippy_lints/src/floating_point_arithmetic.rs | 108 +++++++++--------- ...fma.fixed => floating_point_mul_add.fixed} | 0 ...point_fma.rs => floating_point_mul_add.rs} | 0 ...a.stderr => floating_point_mul_add.stderr} | 18 +-- tests/ui/floating_point_powf.fixed | 2 + tests/ui/floating_point_powf.rs | 2 + tests/ui/floating_point_powf.stderr | 24 ++-- 7 files changed, 82 insertions(+), 72 deletions(-) rename tests/ui/{floating_point_fma.fixed => floating_point_mul_add.fixed} (100%) rename tests/ui/{floating_point_fma.rs => floating_point_mul_add.rs} (100%) rename tests/ui/{floating_point_fma.stderr => floating_point_mul_add.stderr} (84%) diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index fbc375c655e6..542ea5132de8 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -9,6 +9,8 @@ use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::source_map::Spanned; + use std::f32::consts as f32_consts; use std::f64::consts as f64_consts; use sugg::{format_numeric_literal, Sugg}; @@ -138,26 +140,29 @@ fn check_log_base(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) // TODO: Lint expressions of the form `(x + y).ln()` where y > 1 and // suggest usage of `(x + (y - 1)).ln_1p()` instead fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { - if_chain! { - if let ExprKind::Binary(op, ref lhs, ref rhs) = &args[0].kind; - if op.node == BinOpKind::Add; - then { - let recv = match (constant(cx, cx.tables, lhs), constant(cx, cx.tables, rhs)) { - (Some((value, _)), _) if F32(1.0) == value || F64(1.0) == value => rhs, - (_, Some((value, _))) if F32(1.0) == value || F64(1.0) == value => lhs, - _ => return, - }; + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Add, .. + }, + lhs, + rhs, + ) = &args[0].kind + { + let recv = match (constant(cx, cx.tables, lhs), constant(cx, cx.tables, rhs)) { + (Some((value, _)), _) if F32(1.0) == value || F64(1.0) == value => rhs, + (_, Some((value, _))) if F32(1.0) == value || F64(1.0) == value => lhs, + _ => return, + }; - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "ln(1 + x) can be computed more accurately", - "consider using", - format!("{}.ln_1p()", prepare_receiver_sugg(cx, recv)), - Applicability::MachineApplicable, - ); - } + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "ln(1 + x) can be computed more accurately", + "consider using", + format!("{}.ln_1p()", prepare_receiver_sugg(cx, recv)), + Applicability::MachineApplicable, + ); } } @@ -249,8 +254,7 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { // and suggest usage of `x.exp_m1() - (y - 1)` instead fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { if_chain! { - if let ExprKind::Binary(op, ref lhs, ref rhs) = expr.kind; - if op.node == BinOpKind::Sub; + if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, ref lhs, ref rhs) = expr.kind; if cx.tables.expr_ty(lhs).is_floating_point(); if let Some((value, _)) = constant(cx, cx.tables, rhs); if F32(1.0) == value || F64(1.0) == value; @@ -276,8 +280,7 @@ fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { fn is_float_mul_expr<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> { if_chain! { - if let ExprKind::Binary(op, ref lhs, ref rhs) = &expr.kind; - if let BinOpKind::Mul = op.node; + if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref lhs, ref rhs) = &expr.kind; if cx.tables.expr_ty(lhs).is_floating_point(); if cx.tables.expr_ty(rhs).is_floating_point(); then { @@ -289,34 +292,37 @@ fn is_float_mul_expr<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'a>) -> Option } // TODO: Fix rust-lang/rust-clippy#4735 -fn check_fma(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { - if_chain! { - if let ExprKind::Binary(op, lhs, rhs) = &expr.kind; - if let BinOpKind::Add = op.node; - then { - let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) { - (inner_lhs, inner_rhs, rhs) - } else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) { - (inner_lhs, inner_rhs, lhs) - } else { - return; - }; +fn check_mul_add(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Add, .. + }, + lhs, + rhs, + ) = &expr.kind + { + let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) { + (inner_lhs, inner_rhs, rhs) + } else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) { + (inner_lhs, inner_rhs, lhs) + } else { + return; + }; - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "multiply and add expressions can be calculated more efficiently and accurately", - "consider using", - format!( - "{}.mul_add({}, {})", - prepare_receiver_sugg(cx, recv), - Sugg::hir(cx, arg1, ".."), - Sugg::hir(cx, arg2, ".."), - ), - Applicability::MachineApplicable, - ); - } + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "multiply and add expressions can be calculated more efficiently and accurately", + "consider using", + format!( + "{}.mul_add({}, {})", + prepare_receiver_sugg(cx, recv), + Sugg::hir(cx, arg1, ".."), + Sugg::hir(cx, arg2, ".."), + ), + Applicability::MachineApplicable, + ); } } @@ -335,7 +341,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic { } } else { check_expm1(cx, expr); - check_fma(cx, expr); + check_mul_add(cx, expr); } } } diff --git a/tests/ui/floating_point_fma.fixed b/tests/ui/floating_point_mul_add.fixed similarity index 100% rename from tests/ui/floating_point_fma.fixed rename to tests/ui/floating_point_mul_add.fixed diff --git a/tests/ui/floating_point_fma.rs b/tests/ui/floating_point_mul_add.rs similarity index 100% rename from tests/ui/floating_point_fma.rs rename to tests/ui/floating_point_mul_add.rs diff --git a/tests/ui/floating_point_fma.stderr b/tests/ui/floating_point_mul_add.stderr similarity index 84% rename from tests/ui/floating_point_fma.stderr rename to tests/ui/floating_point_mul_add.stderr index 5c653360ebc8..2dfbf562d15f 100644 --- a/tests/ui/floating_point_fma.stderr +++ b/tests/ui/floating_point_mul_add.stderr @@ -1,5 +1,5 @@ error: multiply and add expressions can be calculated more efficiently and accurately - --> $DIR/floating_point_fma.rs:10:13 + --> $DIR/floating_point_mul_add.rs:10:13 | LL | let _ = a * b + c; | ^^^^^^^^^ help: consider using: `a.mul_add(b, c)` @@ -7,49 +7,49 @@ LL | let _ = a * b + c; = note: `-D clippy::suboptimal-flops` implied by `-D warnings` error: multiply and add expressions can be calculated more efficiently and accurately - --> $DIR/floating_point_fma.rs:11:13 + --> $DIR/floating_point_mul_add.rs:11:13 | LL | let _ = c + a * b; | ^^^^^^^^^ help: consider using: `a.mul_add(b, c)` error: multiply and add expressions can be calculated more efficiently and accurately - --> $DIR/floating_point_fma.rs:12:13 + --> $DIR/floating_point_mul_add.rs:12:13 | LL | let _ = a + 2.0 * 4.0; | ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4.0, a)` error: multiply and add expressions can be calculated more efficiently and accurately - --> $DIR/floating_point_fma.rs:13:13 + --> $DIR/floating_point_mul_add.rs:13:13 | LL | let _ = a + 2. * 4.; | ^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4., a)` error: multiply and add expressions can be calculated more efficiently and accurately - --> $DIR/floating_point_fma.rs:15:13 + --> $DIR/floating_point_mul_add.rs:15:13 | LL | let _ = (a * b) + c; | ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)` error: multiply and add expressions can be calculated more efficiently and accurately - --> $DIR/floating_point_fma.rs:16:13 + --> $DIR/floating_point_mul_add.rs:16:13 | LL | let _ = c + (a * b); | ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)` error: multiply and add expressions can be calculated more efficiently and accurately - --> $DIR/floating_point_fma.rs:17:13 + --> $DIR/floating_point_mul_add.rs:17:13 | LL | let _ = a * b * c + d; | ^^^^^^^^^^^^^ help: consider using: `(a * b).mul_add(c, d)` error: multiply and add expressions can be calculated more efficiently and accurately - --> $DIR/floating_point_fma.rs:19:13 + --> $DIR/floating_point_mul_add.rs:19:13 | LL | let _ = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c))` error: multiply and add expressions can be calculated more efficiently and accurately - --> $DIR/floating_point_fma.rs:20:13 + --> $DIR/floating_point_mul_add.rs:20:13 | LL | let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1234.567_f64.mul_add(45.67834_f64, 0.0004_f64)` diff --git a/tests/ui/floating_point_powf.fixed b/tests/ui/floating_point_powf.fixed index 54d130a22beb..c5d900de3294 100644 --- a/tests/ui/floating_point_powf.fixed +++ b/tests/ui/floating_point_powf.fixed @@ -15,6 +15,7 @@ fn main() { let _ = x.powi(-2); let _ = x.powi(16_777_215); let _ = x.powi(-16_777_215); + // Cases where the lint shouldn't be applied let _ = x.powf(2.1); let _ = x.powf(-2.1); let _ = x.powf(16_777_216.0); @@ -33,6 +34,7 @@ fn main() { let _ = x.powi(-2); let _ = x.powi(-2_147_483_648); let _ = x.powi(2_147_483_647); + // Cases where the lint shouldn't be applied let _ = x.powf(2.1); let _ = x.powf(-2.1); let _ = x.powf(-2_147_483_649.0); diff --git a/tests/ui/floating_point_powf.rs b/tests/ui/floating_point_powf.rs index c1b64d704cd6..cc75e230f7d0 100644 --- a/tests/ui/floating_point_powf.rs +++ b/tests/ui/floating_point_powf.rs @@ -15,6 +15,7 @@ fn main() { let _ = x.powf(-2.0); let _ = x.powf(16_777_215.0); let _ = x.powf(-16_777_215.0); + // Cases where the lint shouldn't be applied let _ = x.powf(2.1); let _ = x.powf(-2.1); let _ = x.powf(16_777_216.0); @@ -33,6 +34,7 @@ fn main() { let _ = x.powf(-2.0); let _ = x.powf(-2_147_483_648.0); let _ = x.powf(2_147_483_647.0); + // Cases where the lint shouldn't be applied let _ = x.powf(2.1); let _ = x.powf(-2.1); let _ = x.powf(-2_147_483_649.0); diff --git a/tests/ui/floating_point_powf.stderr b/tests/ui/floating_point_powf.stderr index 2b912c5940ed..8f0544d4b582 100644 --- a/tests/ui/floating_point_powf.stderr +++ b/tests/ui/floating_point_powf.stderr @@ -73,73 +73,73 @@ LL | let _ = x.powf(-16_777_215.0); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(-16_777_215)` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:24:13 + --> $DIR/floating_point_powf.rs:25:13 | LL | let _ = 2f64.powf(x); | ^^^^^^^^^^^^ help: consider using: `x.exp2()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:25:13 + --> $DIR/floating_point_powf.rs:26:13 | LL | let _ = 2f64.powf(3.1); | ^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp2()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:26:13 + --> $DIR/floating_point_powf.rs:27:13 | LL | let _ = 2f64.powf(-3.1); | ^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp2()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:27:13 + --> $DIR/floating_point_powf.rs:28:13 | LL | let _ = std::f64::consts::E.powf(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:28:13 + --> $DIR/floating_point_powf.rs:29:13 | LL | let _ = std::f64::consts::E.powf(3.1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp()` error: exponent for bases 2 and e can be computed more accurately - --> $DIR/floating_point_powf.rs:29:13 + --> $DIR/floating_point_powf.rs:30:13 | LL | let _ = std::f64::consts::E.powf(-3.1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp()` error: square-root of a number can be computed more efficiently and accurately - --> $DIR/floating_point_powf.rs:30:13 + --> $DIR/floating_point_powf.rs:31:13 | LL | let _ = x.powf(1.0 / 2.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()` error: cube-root of a number can be computed more accurately - --> $DIR/floating_point_powf.rs:31:13 + --> $DIR/floating_point_powf.rs:32:13 | LL | let _ = x.powf(1.0 / 3.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` error: exponentiation with integer powers can be computed more efficiently - --> $DIR/floating_point_powf.rs:32:13 + --> $DIR/floating_point_powf.rs:33:13 | LL | let _ = x.powf(2.0); | ^^^^^^^^^^^ help: consider using: `x.powi(2)` error: exponentiation with integer powers can be computed more efficiently - --> $DIR/floating_point_powf.rs:33:13 + --> $DIR/floating_point_powf.rs:34:13 | LL | let _ = x.powf(-2.0); | ^^^^^^^^^^^^ help: consider using: `x.powi(-2)` error: exponentiation with integer powers can be computed more efficiently - --> $DIR/floating_point_powf.rs:34:13 + --> $DIR/floating_point_powf.rs:35:13 | LL | let _ = x.powf(-2_147_483_648.0); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(-2_147_483_648)` error: exponentiation with integer powers can be computed more efficiently - --> $DIR/floating_point_powf.rs:35:13 + --> $DIR/floating_point_powf.rs:36:13 | LL | let _ = x.powf(2_147_483_647.0); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2_147_483_647)` From ff0d44e45a27e688b5ee5447dc9175d5e72b37c9 Mon Sep 17 00:00:00 2001 From: Krishna Sai Veera Reddy Date: Sun, 23 Feb 2020 21:06:55 -0800 Subject: [PATCH 142/243] Add `imprecise_flops` lint Add lint to detect floating point operations that can be computed more accurately at the cost of performance. `cbrt`, `ln_1p` and `exp_m1` library functions call their equivalent cmath implementations which is slower but more accurate so moving checks for these under this new lint. --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/floating_point_arithmetic.rs | 55 +++++++++++++++---- clippy_lints/src/lib.rs | 2 + src/lintlist/mod.rs | 9 ++- tests/ui/floating_point_exp.fixed | 2 +- tests/ui/floating_point_exp.rs | 2 +- tests/ui/floating_point_exp.stderr | 2 +- tests/ui/floating_point_log.fixed | 2 +- tests/ui/floating_point_log.rs | 2 +- tests/ui/floating_point_log.stderr | 2 + tests/ui/floating_point_powf.fixed | 2 +- tests/ui/floating_point_powf.rs | 2 +- tests/ui/floating_point_powf.stderr | 2 + 14 files changed, 67 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce696aa85501..99e84ea51931 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1169,6 +1169,7 @@ Released 2018-09-13 [`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond [`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher [`implicit_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return +[`imprecise_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#imprecise_flops [`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping [`indexing_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing [`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask diff --git a/README.md b/README.md index 3103f9608398..1300c5ad47bf 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 357 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 358 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 542ea5132de8..eed4f58cf902 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -16,6 +16,39 @@ use std::f64::consts as f64_consts; use sugg::{format_numeric_literal, Sugg}; use syntax::ast; +declare_clippy_lint! { + /// **What it does:** Looks for floating-point expressions that + /// can be expressed using built-in methods to improve accuracy + /// at the cost of performance. + /// + /// **Why is this bad?** Negatively impacts accuracy. + /// + /// **Known problems:** None + /// + /// **Example:** + /// + /// ```rust + /// + /// let a = 3f32; + /// let _ = a.powf(1.0 / 3.0); + /// let _ = (1.0 + a).ln(); + /// let _ = a.exp() - 1.0; + /// ``` + /// + /// is better expressed as + /// + /// ```rust + /// + /// let a = 3f32; + /// let _ = a.cbrt(); + /// let _ = a.ln_1p(); + /// let _ = a.exp_m1(); + /// ``` + pub IMPRECISE_FLOPS, + nursery, + "usage of imprecise floating point operations" +} + declare_clippy_lint! { /// **What it does:** Looks for floating-point expressions that /// can be expressed using built-in methods to improve both @@ -34,12 +67,9 @@ declare_clippy_lint! { /// let _ = (2f32).powf(a); /// let _ = E.powf(a); /// let _ = a.powf(1.0 / 2.0); - /// let _ = a.powf(1.0 / 3.0); /// let _ = a.log(2.0); /// let _ = a.log(10.0); /// let _ = a.log(E); - /// let _ = (1.0 + a).ln(); - /// let _ = a.exp() - 1.0; /// let _ = a.powf(2.0); /// let _ = a * 2.0 + 4.0; /// ``` @@ -53,12 +83,9 @@ declare_clippy_lint! { /// let _ = a.exp2(); /// let _ = a.exp(); /// let _ = a.sqrt(); - /// let _ = a.cbrt(); /// let _ = a.log2(); /// let _ = a.log10(); /// let _ = a.ln(); - /// let _ = a.ln_1p(); - /// let _ = a.exp_m1(); /// let _ = a.powi(2); /// let _ = a.mul_add(2.0, 4.0); /// ``` @@ -67,7 +94,10 @@ declare_clippy_lint! { "usage of sub-optimal floating point operations" } -declare_lint_pass!(FloatingPointArithmetic => [SUBOPTIMAL_FLOPS]); +declare_lint_pass!(FloatingPointArithmetic => [ + IMPRECISE_FLOPS, + SUBOPTIMAL_FLOPS +]); // Returns the specialized log method for a given base if base is constant // and is one of 2, 10 and e @@ -156,7 +186,7 @@ fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { span_lint_and_sugg( cx, - SUBOPTIMAL_FLOPS, + IMPRECISE_FLOPS, expr.span, "ln(1 + x) can be computed more accurately", "consider using", @@ -215,18 +245,21 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { // Check argument if let Some((value, _)) = constant(cx, cx.tables, &args[1]) { - let (help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value { + let (lint, help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value { ( + SUBOPTIMAL_FLOPS, "square-root of a number can be computed more efficiently and accurately", format!("{}.sqrt()", Sugg::hir(cx, &args[0], "..")), ) } else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value { ( + IMPRECISE_FLOPS, "cube-root of a number can be computed more accurately", format!("{}.cbrt()", Sugg::hir(cx, &args[0], "..")), ) } else if let Some(exponent) = get_integer_from_float_constant(&value) { ( + SUBOPTIMAL_FLOPS, "exponentiation with integer powers can be computed more efficiently", format!( "{}.powi({})", @@ -240,7 +273,7 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { span_lint_and_sugg( cx, - SUBOPTIMAL_FLOPS, + lint, expr.span, help, "consider using", @@ -264,7 +297,7 @@ fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { then { span_lint_and_sugg( cx, - SUBOPTIMAL_FLOPS, + IMPRECISE_FLOPS, expr.span, "(e.pow(x) - 1) can be computed more accurately", "consider using", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 503eb9ec10d6..c732657b2e57 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -538,6 +538,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &fallible_impl_from::FALLIBLE_IMPL_FROM, &float_literal::EXCESSIVE_PRECISION, &float_literal::LOSSY_FLOAT_LITERAL, + &floating_point_arithmetic::IMPRECISE_FLOPS, &floating_point_arithmetic::SUBOPTIMAL_FLOPS, &format::USELESS_FORMAT, &formatting::POSSIBLE_MISSING_COMMA, @@ -1648,6 +1649,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![ LintId::of(&attrs::EMPTY_LINE_AFTER_OUTER_ATTR), LintId::of(&fallible_impl_from::FALLIBLE_IMPL_FROM), + LintId::of(&floating_point_arithmetic::IMPRECISE_FLOPS), LintId::of(&floating_point_arithmetic::SUBOPTIMAL_FLOPS), LintId::of(&missing_const_for_fn::MISSING_CONST_FOR_FN), LintId::of(&mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 5b4aad347af2..15e6a4b6036a 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -6,7 +6,7 @@ pub use lint::Lint; pub use lint::LINT_LEVELS; // begin lint list, do not remove this comment, it’s used in `update_lints` -pub const ALL_LINTS: [Lint; 357] = [ +pub const ALL_LINTS: [Lint; 358] = [ Lint { name: "absurd_extreme_comparisons", group: "correctness", @@ -749,6 +749,13 @@ pub const ALL_LINTS: [Lint; 357] = [ deprecation: None, module: "implicit_return", }, + Lint { + name: "imprecise_flops", + group: "nursery", + desc: "usage of imprecise floating point operations", + deprecation: None, + module: "floating_point_arithmetic", + }, Lint { name: "inconsistent_digit_grouping", group: "style", diff --git a/tests/ui/floating_point_exp.fixed b/tests/ui/floating_point_exp.fixed index 1f534e3705d8..ae7805fdf018 100644 --- a/tests/ui/floating_point_exp.fixed +++ b/tests/ui/floating_point_exp.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![warn(clippy::suboptimal_flops)] +#![warn(clippy::imprecise_flops)] fn main() { let x = 2f32; diff --git a/tests/ui/floating_point_exp.rs b/tests/ui/floating_point_exp.rs index bed8d3121408..27e0b9bcbc93 100644 --- a/tests/ui/floating_point_exp.rs +++ b/tests/ui/floating_point_exp.rs @@ -1,5 +1,5 @@ // run-rustfix -#![warn(clippy::suboptimal_flops)] +#![warn(clippy::imprecise_flops)] fn main() { let x = 2f32; diff --git a/tests/ui/floating_point_exp.stderr b/tests/ui/floating_point_exp.stderr index 7882b2c24e3a..5cd999ad47cd 100644 --- a/tests/ui/floating_point_exp.stderr +++ b/tests/ui/floating_point_exp.stderr @@ -4,7 +4,7 @@ error: (e.pow(x) - 1) can be computed more accurately LL | let _ = x.exp() - 1.0; | ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()` | - = note: `-D clippy::suboptimal-flops` implied by `-D warnings` + = note: `-D clippy::imprecise-flops` implied by `-D warnings` error: (e.pow(x) - 1) can be computed more accurately --> $DIR/floating_point_exp.rs:7:13 diff --git a/tests/ui/floating_point_log.fixed b/tests/ui/floating_point_log.fixed index afe72a8dd110..42c5e5d2bae2 100644 --- a/tests/ui/floating_point_log.fixed +++ b/tests/ui/floating_point_log.fixed @@ -1,6 +1,6 @@ // run-rustfix #![allow(dead_code, clippy::double_parens)] -#![warn(clippy::suboptimal_flops)] +#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)] const TWO: f32 = 2.0; const E: f32 = std::f32::consts::E; diff --git a/tests/ui/floating_point_log.rs b/tests/ui/floating_point_log.rs index 785b5a3bc487..8be0d9ad56fc 100644 --- a/tests/ui/floating_point_log.rs +++ b/tests/ui/floating_point_log.rs @@ -1,6 +1,6 @@ // run-rustfix #![allow(dead_code, clippy::double_parens)] -#![warn(clippy::suboptimal_flops)] +#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)] const TWO: f32 = 2.0; const E: f32 = std::f32::consts::E; diff --git a/tests/ui/floating_point_log.stderr b/tests/ui/floating_point_log.stderr index cb0bb6d652a8..943fbdb0b832 100644 --- a/tests/ui/floating_point_log.stderr +++ b/tests/ui/floating_point_log.stderr @@ -53,6 +53,8 @@ error: ln(1 + x) can be computed more accurately | LL | let _ = (1f32 + 2.).ln(); | ^^^^^^^^^^^^^^^^ help: consider using: `2.0f32.ln_1p()` + | + = note: `-D clippy::imprecise-flops` implied by `-D warnings` error: ln(1 + x) can be computed more accurately --> $DIR/floating_point_log.rs:25:13 diff --git a/tests/ui/floating_point_powf.fixed b/tests/ui/floating_point_powf.fixed index c5d900de3294..78a9d44829bb 100644 --- a/tests/ui/floating_point_powf.fixed +++ b/tests/ui/floating_point_powf.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![warn(clippy::suboptimal_flops)] +#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)] fn main() { let x = 3f32; diff --git a/tests/ui/floating_point_powf.rs b/tests/ui/floating_point_powf.rs index cc75e230f7d0..dbc1cac5cb43 100644 --- a/tests/ui/floating_point_powf.rs +++ b/tests/ui/floating_point_powf.rs @@ -1,5 +1,5 @@ // run-rustfix -#![warn(clippy::suboptimal_flops)] +#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)] fn main() { let x = 3f32; diff --git a/tests/ui/floating_point_powf.stderr b/tests/ui/floating_point_powf.stderr index 8f0544d4b582..ad5163f0079b 100644 --- a/tests/ui/floating_point_powf.stderr +++ b/tests/ui/floating_point_powf.stderr @@ -47,6 +47,8 @@ error: cube-root of a number can be computed more accurately | LL | let _ = x.powf(1.0 / 3.0); | ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()` + | + = note: `-D clippy::imprecise-flops` implied by `-D warnings` error: exponentiation with integer powers can be computed more efficiently --> $DIR/floating_point_powf.rs:14:13 From 7c760e5f832f660df03d4f4fcb16512e602f3438 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 27 Feb 2020 12:19:18 +0900 Subject: [PATCH 143/243] Rustup to rust-lang/rust#61812 --- tests/ui/missing-doc-impl.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/missing-doc-impl.rs b/tests/ui/missing-doc-impl.rs index 1317521f7366..57af84dcdf4d 100644 --- a/tests/ui/missing-doc-impl.rs +++ b/tests/ui/missing-doc-impl.rs @@ -46,7 +46,7 @@ pub trait D { } /// dox -pub trait E { +pub trait E: Sized { type AssociatedType; type AssociatedTypeDef = Self; From 43e760ce1dfcf92328d81fcf761f23bcdc18c0cd Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 27 Feb 2020 13:40:48 +0900 Subject: [PATCH 144/243] Update git2 to 0.12 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c1a410cf5c82..cfcdaf22291c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ clippy_lints = { version = "0.0.212", path = "clippy_lints" } regex = "1" semver = "0.9" rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"} -git2 = { version = "0.11", optional = true } +git2 = { version = "0.12", optional = true } tempfile = { version = "3.1.0", optional = true } lazy_static = "1.0" From f8224977b1948c1b0fe4395da9516ca68557e7c8 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 27 Feb 2020 17:56:39 +0100 Subject: [PATCH 145/243] Fix deploy script for tag deploys --- .github/deploy.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/deploy.sh b/.github/deploy.sh index b1f572d2b455..9ef9678ee92d 100644 --- a/.github/deploy.sh +++ b/.github/deploy.sh @@ -33,7 +33,17 @@ if git diff --exit-code --quiet; then exit 0 fi -git add . -git commit -m "Automatic deploy to GitHub Pages: ${SHA}" +if [[ -n $TAG_NAME ]]; then + # Add the new dir + git add $TAG_NAME + # Update the symlink + git add stable + # Update versions file + git add versions.json + git commit -m "Add documentation for ${TAG_NAME} release: ${SHA}" +else + git add . + git commit -m "Automatic deploy to GitHub Pages: ${SHA}" +fi git push "$SSH_REPO" "$TARGET_BRANCH" From ce0dc9b70e1f021043bb3b4edfb8068590bc8325 Mon Sep 17 00:00:00 2001 From: JarredAllen Date: Thu, 27 Feb 2020 22:31:41 -0800 Subject: [PATCH 146/243] Created floating point abs lint and test, but not yet run --- clippy_lints/src/floating_point_arithmetic.rs | 75 ++++++++++++++++++- tests/ui/floating_point_abs.rs | 59 +++++++++++++++ 2 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 tests/ui/floating_point_abs.rs diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index eed4f58cf902..810c6e1412a9 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -2,11 +2,11 @@ use crate::consts::{ constant, Constant, Constant::{F32, F64}, }; -use crate::utils::{span_lint_and_sugg, sugg}; +use crate::utils::{higher, span_lint_and_sugg, sugg, SpanlessEq}; use if_chain::if_chain; use rustc::ty; use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; +use rustc_hir::{BinOpKind, Expr, ExprKind, Lit, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; @@ -14,7 +14,7 @@ use rustc_span::source_map::Spanned; use std::f32::consts as f32_consts; use std::f64::consts as f64_consts; use sugg::{format_numeric_literal, Sugg}; -use syntax::ast; +use syntax::ast::{self, FloatTy, LitFloatType, LitKind}; declare_clippy_lint! { /// **What it does:** Looks for floating-point expressions that @@ -72,6 +72,16 @@ declare_clippy_lint! { /// let _ = a.log(E); /// let _ = a.powf(2.0); /// let _ = a * 2.0 + 4.0; + /// let _ = if a < 0.0 { + /// -a + /// } else { + /// a + /// } + /// let _ = if a < 0.0 { + /// a + /// } else { + /// -a + /// } /// ``` /// /// is better expressed as @@ -88,6 +98,8 @@ declare_clippy_lint! { /// let _ = a.ln(); /// let _ = a.powi(2); /// let _ = a.mul_add(2.0, 4.0); + /// let _ = a.abs(); + /// let _ = -a.abs(); /// ``` pub SUBOPTIMAL_FLOPS, nursery, @@ -359,6 +371,62 @@ fn check_mul_add(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { } } +/// Returns true iff expr is an expression which tests whether or not +/// test is positive or an expression which tests whether or not test +/// is nonnegative. +/// Used for check-custom-abs function below +fn is_testing_positive(cx: &LateContext<'_, '_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool { + if let ExprKind::Binary(Spanned { node: op, .. }, left, right) = expr.kind { + match op { + BinOpKind::Gt | BinOpKind::Ge => is_zero(right) && are_exprs_equal(cx, left, test), + BinOpKind::Lt | BinOpKind::Le => is_zero(left) && are_exprs_equal(cx, right, test), + _ => false, + } + } else { + false + } +} + +fn are_exprs_equal(cx: &LateContext<'_, '_>, expr1: &Expr<'_>, expr2: &Expr<'_>) -> bool { + SpanlessEq::new(cx).ignore_fn().eq_expr(expr1, expr2) +} + +/// Returns true iff expr is some zero literal +fn is_zero(expr: &Expr<'_>) -> bool { + if let ExprKind::Lit(Lit { node: lit, .. }) = &expr.kind { + match lit { + LitKind::Int(0, _) => true, + LitKind::Float(symb, LitFloatType::Unsuffixed) + | LitKind::Float(symb, LitFloatType::Suffixed(FloatTy::F64)) => { + symb.as_str().parse::().unwrap() == 0.0 + }, + LitKind::Float(symb, LitFloatType::Suffixed(FloatTy::F32)) => symb.as_str().parse::().unwrap() == 0.0, + _ => false, + } + } else { + false + } +} + +fn check_custom_abs(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { +// if let Some((cond, body, Some(else_body))) = higher::if_block(&expr) { + // Check for the positive-first variant +// if let ExprKind::Unary(UnOp::UnNeg, expr) = else_body.kind { +// if are_exprs_equal(cx, expr, body) && is_testing_positive(cx, cond, body) { + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "This looks like you've implemented your own absolute value function", + "try", + "a.abs()".to_string(),//format!("{:?}.abs()", body), + Applicability::MachineApplicable, + ); +// } +// } +// } +} + impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::MethodCall(ref path, _, args) = &expr.kind { @@ -375,6 +443,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic { } else { check_expm1(cx, expr); check_mul_add(cx, expr); + check_custom_abs(cx, expr); } } } diff --git a/tests/ui/floating_point_abs.rs b/tests/ui/floating_point_abs.rs new file mode 100644 index 000000000000..2cb1db095413 --- /dev/null +++ b/tests/ui/floating_point_abs.rs @@ -0,0 +1,59 @@ +#[warn(clippy::suboptimal_flops)] + +fn fake_abs1(num: f64) -> f64 { + if num >= 0.0 { + num + } else { + -num + } +} + +fn fake_abs2(num: f64) -> f64 { + if 0.0 < num { + num + } else { + -num + } +} + +fn fake_nabs1(num: f64) -> f64 { + if num < 0.0 { + num + } else { + -num + } +} + +fn fake_nabs2(num: f64) -> f64 { + if 0.0 >= num { + num + } else { + -num + } +} + +fn not_fake_abs1(num: f64) -> f64 { + if num > 0.0 { + num + } else { + -num - 1f64 + } +} + +fn not_fake_abs2(num: f64) -> f64 { + if num > 0.0 { + num + 1.0 + } else { + -(num + 1.0) + } +} + +fn not_fake_abs3(num1: f64, num2: f64) -> f64 { + if num1 > 0.0 { + num2 + } else { + -num2 + } +} + +fn main() {} From 5a21661ce54bf2485e90d21282e1fe7be45879af Mon Sep 17 00:00:00 2001 From: JarredAllen Date: Fri, 28 Feb 2020 12:40:13 -0800 Subject: [PATCH 147/243] Some bugfixing --- clippy_lints/src/floating_point_arithmetic.rs | 58 +++++++++++++------ tests/ui/floating_point_abs.rs | 36 ++++++++++++ tests/ui/floating_point_abs.stderr | 14 +++++ 3 files changed, 91 insertions(+), 17 deletions(-) create mode 100644 tests/ui/floating_point_abs.stderr diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 810c6e1412a9..970aeef623ee 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -6,7 +6,7 @@ use crate::utils::{higher, span_lint_and_sugg, sugg, SpanlessEq}; use if_chain::if_chain; use rustc::ty; use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Expr, ExprKind, Lit, UnOp}; +use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Lit, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; @@ -409,22 +409,46 @@ fn is_zero(expr: &Expr<'_>) -> bool { } fn check_custom_abs(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { -// if let Some((cond, body, Some(else_body))) = higher::if_block(&expr) { - // Check for the positive-first variant -// if let ExprKind::Unary(UnOp::UnNeg, expr) = else_body.kind { -// if are_exprs_equal(cx, expr, body) && is_testing_positive(cx, cond, body) { - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "This looks like you've implemented your own absolute value function", - "try", - "a.abs()".to_string(),//format!("{:?}.abs()", body), - Applicability::MachineApplicable, - ); -// } -// } -// } + if let Some((cond, body, Some(else_body))) = higher::if_block(&expr) { + if let ExprKind::Block( + Block { + stmts: [], + expr: + Some(Expr { + kind: ExprKind::Unary(UnOp::UnNeg, else_expr), + .. + }), + .. + }, + _, + ) = else_body.kind + { + if let ExprKind::Block( + Block { + stmts: [], + expr: Some(body), + .. + }, + _, + ) = &body.kind + { + if are_exprs_equal(cx, else_expr, body) { + dbg!("if (cond) body else -body\nbody: {:?}", &body.kind); + if is_testing_positive(cx, cond, body) { + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "This looks like you've implemented your own absolute value function", + "try", + format!("{}.abs()", Sugg::hir(cx, body, "..")), + Applicability::MachineApplicable, + ); + } + } + } + } + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic { diff --git a/tests/ui/floating_point_abs.rs b/tests/ui/floating_point_abs.rs index 2cb1db095413..0efc7092899a 100644 --- a/tests/ui/floating_point_abs.rs +++ b/tests/ui/floating_point_abs.rs @@ -1,4 +1,8 @@ #[warn(clippy::suboptimal_flops)] +struct A { + a: f64, + b: f64 +} fn fake_abs1(num: f64) -> f64 { if num >= 0.0 { @@ -16,6 +20,14 @@ fn fake_abs2(num: f64) -> f64 { } } +fn fake_abs3(a: A) -> f64 { + if a.a > 0.0 { + a.a + } else { + -a.a + } +} + fn fake_nabs1(num: f64) -> f64 { if num < 0.0 { num @@ -32,6 +44,14 @@ fn fake_nabs2(num: f64) -> f64 { } } +fn fake_nabs3(a: A) -> A { + A { a: if a.a >= 0.0 { + a.a + } else { + -a.a + }, b: a.b } +} + fn not_fake_abs1(num: f64) -> f64 { if num > 0.0 { num @@ -56,4 +76,20 @@ fn not_fake_abs3(num1: f64, num2: f64) -> f64 { } } +fn not_fake_abs4(a: A) -> f64 { + if a.a > 0.0 { + a.b + } else { + -a.b + } +} + +fn not_fake_abs5(a: A) -> f64 { + if a.a > 0.0 { + a.a + } else { + -a.b + } +} + fn main() {} diff --git a/tests/ui/floating_point_abs.stderr b/tests/ui/floating_point_abs.stderr new file mode 100644 index 000000000000..bbd67de17c00 --- /dev/null +++ b/tests/ui/floating_point_abs.stderr @@ -0,0 +1,14 @@ +error: This looks like you've implemented your own absolute value function + --> $DIR/floating_point_abs.rs:4:5 + | +LL | / if num >= 0.0 { +LL | | num +LL | | } else { +LL | | -num +LL | | } + | |_____^ help: try: `num.abs()` + | + = note: `-D clippy::suboptimal-flops` implied by `-D warnings` + +error: aborting due to previous error + From 1e29b36e4e6c320fd9d5aeb44e3baf1d539b3ca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 28 Feb 2020 22:00:20 +0100 Subject: [PATCH 148/243] add test for #5238 --- tests/ui/crashes/ice-5238.rs | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 tests/ui/crashes/ice-5238.rs diff --git a/tests/ui/crashes/ice-5238.rs b/tests/ui/crashes/ice-5238.rs new file mode 100644 index 000000000000..989eb6d44855 --- /dev/null +++ b/tests/ui/crashes/ice-5238.rs @@ -0,0 +1,9 @@ +// Regression test for #5238 / https://github.com/rust-lang/rust/pull/69562 + +#![feature(generators, generator_trait)] + +fn main() { + let _ = || { + yield; + }; +} From 028cddb95628252180bf6146b445e146dcdef8b2 Mon Sep 17 00:00:00 2001 From: JarredAllen Date: Sat, 29 Feb 2020 13:46:59 -0800 Subject: [PATCH 149/243] Finished checking for cases of absolute values --- clippy_lints/src/floating_point_arithmetic.rs | 75 +++++++++++++------ tests/ui/floating_point_abs.rs | 23 +++++- tests/ui/floating_point_abs.stderr | 75 ++++++++++++++++++- 3 files changed, 145 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 970aeef623ee..8a6ae10ab0b9 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -387,6 +387,18 @@ fn is_testing_positive(cx: &LateContext<'_, '_>, expr: &Expr<'_>, test: &Expr<'_ } } +fn is_testing_negative(cx: &LateContext<'_, '_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool { + if let ExprKind::Binary(Spanned { node: op, .. }, left, right) = expr.kind { + match op { + BinOpKind::Gt | BinOpKind::Ge => is_zero(left) && are_exprs_equal(cx, right, test), + BinOpKind::Lt | BinOpKind::Le => is_zero(right) && are_exprs_equal(cx, left, test), + _ => false, + } + } else { + false + } +} + fn are_exprs_equal(cx: &LateContext<'_, '_>, expr1: &Expr<'_>, expr2: &Expr<'_>) -> bool { SpanlessEq::new(cx).ignore_fn().eq_expr(expr1, expr2) } @@ -410,30 +422,9 @@ fn is_zero(expr: &Expr<'_>) -> bool { fn check_custom_abs(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { if let Some((cond, body, Some(else_body))) = higher::if_block(&expr) { - if let ExprKind::Block( - Block { - stmts: [], - expr: - Some(Expr { - kind: ExprKind::Unary(UnOp::UnNeg, else_expr), - .. - }), - .. - }, - _, - ) = else_body.kind - { - if let ExprKind::Block( - Block { - stmts: [], - expr: Some(body), - .. - }, - _, - ) = &body.kind - { + if let ExprKind::Block( Block { stmts: [], expr: Some(Expr { kind: ExprKind::Unary(UnOp::UnNeg, else_expr), .. }), .. }, _,) = else_body.kind { + if let ExprKind::Block( Block { stmts: [], expr: Some(body), .. }, _,) = &body.kind { if are_exprs_equal(cx, else_expr, body) { - dbg!("if (cond) body else -body\nbody: {:?}", &body.kind); if is_testing_positive(cx, cond, body) { span_lint_and_sugg( cx, @@ -444,6 +435,44 @@ fn check_custom_abs(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { format!("{}.abs()", Sugg::hir(cx, body, "..")), Applicability::MachineApplicable, ); + } else if is_testing_negative(cx, cond, body) { + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "This looks like you've implemented your own negative absolute value function", + "try", + format!("-{}.abs()", Sugg::hir(cx, body, "..")), + Applicability::MachineApplicable, + ); + } + } + } + } + if let ExprKind::Block( Block { stmts: [], expr: Some(Expr { kind: ExprKind::Unary(UnOp::UnNeg, else_expr), .. }), .. }, _,) = &body.kind + { + if let ExprKind::Block( Block { stmts: [], expr: Some(body), .. }, _,) = &else_body.kind { + if are_exprs_equal(cx, else_expr, body) { + if is_testing_negative(cx, cond, body) { + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "This looks like you've implemented your own absolute value function", + "try", + format!("{}.abs()", Sugg::hir(cx, body, "..")), + Applicability::MachineApplicable, + ); + } else if is_testing_positive(cx, cond, body) { + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "This looks like you've implemented your own negative absolute value function", + "try", + format!("-{}.abs()", Sugg::hir(cx, body, "..")), + Applicability::MachineApplicable, + ); } } } diff --git a/tests/ui/floating_point_abs.rs b/tests/ui/floating_point_abs.rs index 0efc7092899a..40d2ff7e8596 100644 --- a/tests/ui/floating_point_abs.rs +++ b/tests/ui/floating_point_abs.rs @@ -1,4 +1,5 @@ -#[warn(clippy::suboptimal_flops)] +#![warn(clippy::suboptimal_flops)] + struct A { a: f64, b: f64 @@ -28,6 +29,22 @@ fn fake_abs3(a: A) -> f64 { } } +fn fake_abs4(num: f64) -> f64 { + if 0.0 >= num { + -num + } else { + num + } +} + +fn fake_abs5(a: A) -> f64 { + if a.a < 0.0 { + -a.a + } else { + a.a + } +} + fn fake_nabs1(num: f64) -> f64 { if num < 0.0 { num @@ -46,9 +63,9 @@ fn fake_nabs2(num: f64) -> f64 { fn fake_nabs3(a: A) -> A { A { a: if a.a >= 0.0 { - a.a - } else { -a.a + } else { + a.a }, b: a.b } } diff --git a/tests/ui/floating_point_abs.stderr b/tests/ui/floating_point_abs.stderr index bbd67de17c00..dd648a8a2726 100644 --- a/tests/ui/floating_point_abs.stderr +++ b/tests/ui/floating_point_abs.stderr @@ -1,5 +1,5 @@ error: This looks like you've implemented your own absolute value function - --> $DIR/floating_point_abs.rs:4:5 + --> $DIR/floating_point_abs.rs:9:5 | LL | / if num >= 0.0 { LL | | num @@ -10,5 +10,76 @@ LL | | } | = note: `-D clippy::suboptimal-flops` implied by `-D warnings` -error: aborting due to previous error +error: This looks like you've implemented your own absolute value function + --> $DIR/floating_point_abs.rs:17:5 + | +LL | / if 0.0 < num { +LL | | num +LL | | } else { +LL | | -num +LL | | } + | |_____^ help: try: `num.abs()` + +error: This looks like you've implemented your own absolute value function + --> $DIR/floating_point_abs.rs:25:5 + | +LL | / if a.a > 0.0 { +LL | | a.a +LL | | } else { +LL | | -a.a +LL | | } + | |_____^ help: try: `a.a.abs()` + +error: This looks like you've implemented your own absolute value function + --> $DIR/floating_point_abs.rs:33:5 + | +LL | / if 0.0 >= num { +LL | | -num +LL | | } else { +LL | | num +LL | | } + | |_____^ help: try: `num.abs()` + +error: This looks like you've implemented your own absolute value function + --> $DIR/floating_point_abs.rs:41:5 + | +LL | / if a.a < 0.0 { +LL | | -a.a +LL | | } else { +LL | | a.a +LL | | } + | |_____^ help: try: `a.a.abs()` + +error: This looks like you've implemented your own negative absolute value function + --> $DIR/floating_point_abs.rs:49:5 + | +LL | / if num < 0.0 { +LL | | num +LL | | } else { +LL | | -num +LL | | } + | |_____^ help: try: `-num.abs()` + +error: This looks like you've implemented your own negative absolute value function + --> $DIR/floating_point_abs.rs:57:5 + | +LL | / if 0.0 >= num { +LL | | num +LL | | } else { +LL | | -num +LL | | } + | |_____^ help: try: `-num.abs()` + +error: This looks like you've implemented your own negative absolute value function + --> $DIR/floating_point_abs.rs:65:12 + | +LL | A { a: if a.a >= 0.0 { + | ____________^ +LL | | -a.a +LL | | } else { +LL | | a.a +LL | | }, b: a.b } + | |_________^ help: try: `-a.a.abs()` + +error: aborting due to 8 previous errors From bfa2691559bf9dd26dc90aa564305aef1f164aec Mon Sep 17 00:00:00 2001 From: JarredAllen Date: Sat, 29 Feb 2020 18:51:39 -0800 Subject: [PATCH 150/243] Run cargo dev fmt --- clippy_lints/src/floating_point_arithmetic.rs | 47 +++++++++++++++++-- tests/ui/floating_point_abs.rs | 11 ++--- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 8a6ae10ab0b9..443ccf178961 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -422,8 +422,28 @@ fn is_zero(expr: &Expr<'_>) -> bool { fn check_custom_abs(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { if let Some((cond, body, Some(else_body))) = higher::if_block(&expr) { - if let ExprKind::Block( Block { stmts: [], expr: Some(Expr { kind: ExprKind::Unary(UnOp::UnNeg, else_expr), .. }), .. }, _,) = else_body.kind { - if let ExprKind::Block( Block { stmts: [], expr: Some(body), .. }, _,) = &body.kind { + if let ExprKind::Block( + Block { + stmts: [], + expr: + Some(Expr { + kind: ExprKind::Unary(UnOp::UnNeg, else_expr), + .. + }), + .. + }, + _, + ) = else_body.kind + { + if let ExprKind::Block( + Block { + stmts: [], + expr: Some(body), + .. + }, + _, + ) = &body.kind + { if are_exprs_equal(cx, else_expr, body) { if is_testing_positive(cx, cond, body) { span_lint_and_sugg( @@ -449,9 +469,28 @@ fn check_custom_abs(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { } } } - if let ExprKind::Block( Block { stmts: [], expr: Some(Expr { kind: ExprKind::Unary(UnOp::UnNeg, else_expr), .. }), .. }, _,) = &body.kind + if let ExprKind::Block( + Block { + stmts: [], + expr: + Some(Expr { + kind: ExprKind::Unary(UnOp::UnNeg, else_expr), + .. + }), + .. + }, + _, + ) = &body.kind { - if let ExprKind::Block( Block { stmts: [], expr: Some(body), .. }, _,) = &else_body.kind { + if let ExprKind::Block( + Block { + stmts: [], + expr: Some(body), + .. + }, + _, + ) = &else_body.kind + { if are_exprs_equal(cx, else_expr, body) { if is_testing_negative(cx, cond, body) { span_lint_and_sugg( diff --git a/tests/ui/floating_point_abs.rs b/tests/ui/floating_point_abs.rs index 40d2ff7e8596..b0c15e57e40f 100644 --- a/tests/ui/floating_point_abs.rs +++ b/tests/ui/floating_point_abs.rs @@ -2,7 +2,7 @@ struct A { a: f64, - b: f64 + b: f64, } fn fake_abs1(num: f64) -> f64 { @@ -62,11 +62,10 @@ fn fake_nabs2(num: f64) -> f64 { } fn fake_nabs3(a: A) -> A { - A { a: if a.a >= 0.0 { - -a.a - } else { - a.a - }, b: a.b } + A { + a: if a.a >= 0.0 { -a.a } else { a.a }, + b: a.b, + } } fn not_fake_abs1(num: f64) -> f64 { From ee739725378105db6f3d8593b12fde6998c9104c Mon Sep 17 00:00:00 2001 From: JarredAllen Date: Sat, 29 Feb 2020 19:11:38 -0800 Subject: [PATCH 151/243] Changed test output to reflect cargo fmt --- tests/ui/floating_point_abs.stderr | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/tests/ui/floating_point_abs.stderr b/tests/ui/floating_point_abs.stderr index dd648a8a2726..44a9dbee5bbd 100644 --- a/tests/ui/floating_point_abs.stderr +++ b/tests/ui/floating_point_abs.stderr @@ -71,15 +71,10 @@ LL | | } | |_____^ help: try: `-num.abs()` error: This looks like you've implemented your own negative absolute value function - --> $DIR/floating_point_abs.rs:65:12 + --> $DIR/floating_point_abs.rs:66:12 | -LL | A { a: if a.a >= 0.0 { - | ____________^ -LL | | -a.a -LL | | } else { -LL | | a.a -LL | | }, b: a.b } - | |_________^ help: try: `-a.a.abs()` +LL | a: if a.a >= 0.0 { -a.a } else { a.a }, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-a.a.abs()` error: aborting due to 8 previous errors From 4253aa7137cb7378acc96133c787e49a345c2b3c Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 1 Mar 2020 12:23:33 +0900 Subject: [PATCH 152/243] Rustup to rust-lang/rust#69592 --- clippy_dev/src/new_lint.rs | 2 +- clippy_lints/src/approx_const.rs | 2 +- clippy_lints/src/as_conversions.rs | 2 +- clippy_lints/src/assertions_on_constants.rs | 2 +- clippy_lints/src/attrs.rs | 4 ++-- clippy_lints/src/bit_mask.rs | 2 +- clippy_lints/src/booleans.rs | 2 +- clippy_lints/src/bytecount.rs | 2 +- clippy_lints/src/cargo_common_metadata.rs | 2 +- clippy_lints/src/checked_conversions.rs | 2 +- clippy_lints/src/cognitive_complexity.rs | 2 +- clippy_lints/src/collapsible_if.rs | 2 +- clippy_lints/src/consts.rs | 2 +- clippy_lints/src/dbg_macro.rs | 4 ++-- clippy_lints/src/doc.rs | 6 +++--- clippy_lints/src/double_parens.rs | 2 +- clippy_lints/src/else_if_without_else.rs | 2 +- clippy_lints/src/enum_clike.rs | 2 +- clippy_lints/src/enum_variants.rs | 2 +- clippy_lints/src/excessive_bools.rs | 2 +- clippy_lints/src/explicit_write.rs | 2 +- clippy_lints/src/float_literal.rs | 2 +- clippy_lints/src/floating_point_arithmetic.rs | 2 +- clippy_lints/src/format.rs | 2 +- clippy_lints/src/formatting.rs | 2 +- clippy_lints/src/functions.rs | 2 +- clippy_lints/src/get_last_with_len.rs | 2 +- clippy_lints/src/if_not_else.rs | 2 +- clippy_lints/src/indexing_slicing.rs | 2 +- clippy_lints/src/inline_fn_without_body.rs | 2 +- clippy_lints/src/int_plus_one.rs | 2 +- clippy_lints/src/items_after_statements.rs | 2 +- clippy_lints/src/len_zero.rs | 2 +- clippy_lints/src/lib.rs | 8 ++++---- clippy_lints/src/literal_representation.rs | 2 +- clippy_lints/src/loops.rs | 2 +- clippy_lints/src/map_clone.rs | 2 +- clippy_lints/src/matches.rs | 2 +- .../src/methods/manual_saturating_arithmetic.rs | 2 +- clippy_lints/src/methods/mod.rs | 2 +- clippy_lints/src/misc.rs | 2 +- clippy_lints/src/misc_early.rs | 10 +++++----- clippy_lints/src/missing_doc.rs | 4 ++-- clippy_lints/src/missing_inline.rs | 2 +- clippy_lints/src/multiple_crate_versions.rs | 2 +- clippy_lints/src/mutex_atomic.rs | 2 +- clippy_lints/src/needless_bool.rs | 2 +- clippy_lints/src/needless_continue.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/non_expressive_names.rs | 10 +++++----- clippy_lints/src/open_options.rs | 2 +- clippy_lints/src/option_env_unwrap.rs | 2 +- clippy_lints/src/panic_unimplemented.rs | 2 +- clippy_lints/src/path_buf_push_overwrite.rs | 2 +- clippy_lints/src/precedence.rs | 6 +++--- clippy_lints/src/ranges.rs | 2 +- clippy_lints/src/redundant_field_names.rs | 2 +- clippy_lints/src/redundant_pattern_matching.rs | 2 +- clippy_lints/src/redundant_static_lifetimes.rs | 2 +- clippy_lints/src/reference.rs | 2 +- clippy_lints/src/regex.rs | 2 +- clippy_lints/src/returns.rs | 4 ++-- clippy_lints/src/single_component_path_imports.rs | 2 +- clippy_lints/src/slow_vector_initialization.rs | 2 +- clippy_lints/src/strings.rs | 2 +- clippy_lints/src/tabs_in_doc_comments.rs | 2 +- clippy_lints/src/transmute.rs | 2 +- clippy_lints/src/transmuting_null.rs | 2 +- clippy_lints/src/types.rs | 2 +- clippy_lints/src/unicode.rs | 2 +- clippy_lints/src/unsafe_removed_from_name.rs | 2 +- clippy_lints/src/utils/attrs.rs | 2 +- clippy_lints/src/utils/author.rs | 4 ++-- clippy_lints/src/utils/conf.rs | 2 +- clippy_lints/src/utils/higher.rs | 2 +- clippy_lints/src/utils/hir_utils.rs | 2 +- clippy_lints/src/utils/inspector.rs | 2 +- clippy_lints/src/utils/internal_lints.rs | 4 ++-- clippy_lints/src/utils/mod.rs | 2 +- clippy_lints/src/utils/ptr.rs | 2 +- clippy_lints/src/utils/sugg.rs | 14 +++++++------- clippy_lints/src/utils/usage.rs | 2 +- clippy_lints/src/wildcard_dependencies.rs | 2 +- clippy_lints/src/write.rs | 6 +++--- 84 files changed, 113 insertions(+), 113 deletions(-) diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index 1149015cfb37..a3ccb2758e25 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -13,7 +13,7 @@ pub fn create(pass: Option<&str>, lint_name: Option<&str>, category: Option<&str match open_files(lint_name) { Ok((mut test_file, mut lint_file)) => { let (pass_type, pass_lifetimes, pass_import, context_import) = match pass { - "early" => ("EarlyLintPass", "", "use syntax::ast::*;", "EarlyContext"), + "early" => ("EarlyLintPass", "", "use rustc_ast::ast::*;", "EarlyContext"), "late" => ("LateLintPass", "<'_, '_>", "use rustc_hir::*;", "LateContext"), _ => { unreachable!("`pass_type` should only ever be `early` or `late`!"); diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 042b83dc386d..0e497e175d66 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -1,10 +1,10 @@ use crate::utils::span_lint; +use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol; use std::f64::consts as f64; -use syntax::ast::{FloatTy, LitFloatType, LitKind}; declare_clippy_lint! { /// **What it does:** Checks for floating point literals that approximate diff --git a/clippy_lints/src/as_conversions.rs b/clippy_lints/src/as_conversions.rs index 5c584b18f4c3..1ec3377193ec 100644 --- a/clippy_lints/src/as_conversions.rs +++ b/clippy_lints/src/as_conversions.rs @@ -1,7 +1,7 @@ use rustc::lint::in_external_macro; +use rustc_ast::ast::{Expr, ExprKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::{Expr, ExprKind}; use crate::utils::span_lint_and_help; diff --git a/clippy_lints/src/assertions_on_constants.rs b/clippy_lints/src/assertions_on_constants.rs index 8a7a48aebf9b..bd9a2a7c40c4 100644 --- a/clippy_lints/src/assertions_on_constants.rs +++ b/clippy_lints/src/assertions_on_constants.rs @@ -2,10 +2,10 @@ use crate::consts::{constant, Constant}; use crate::utils::paths; use crate::utils::{is_direct_expn_of, is_expn_of, match_function_call, snippet_opt, span_lint_and_help}; use if_chain::if_chain; +use rustc_ast::ast::LitKind; use rustc_hir::{Expr, ExprKind, PatKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::LitKind; declare_clippy_lint! { /// **What it does:** Checks for `assert!(true)` and `assert!(false)` calls. diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 5c083cefc8d1..f753d3dc1c7b 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -8,6 +8,8 @@ use crate::utils::{ use if_chain::if_chain; use rustc::lint::in_external_macro; use rustc::ty; +use rustc_ast::ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem}; +use rustc_ast::util::lev_distance::find_best_match_for_name; use rustc_errors::Applicability; use rustc_hir::{ Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitItem, TraitItemKind, TraitMethod, @@ -17,8 +19,6 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; use semver::Version; -use syntax::ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem}; -use syntax::util::lev_distance::find_best_match_for_name; declare_clippy_lint! { /// **What it does:** Checks for items annotated with `#[inline(always)]`, diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 05f85e929614..780535423499 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -2,12 +2,12 @@ use crate::consts::{constant, Constant}; use crate::utils::sugg::Sugg; use crate::utils::{span_lint, span_lint_and_then}; use if_chain::if_chain; +use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; -use syntax::ast::LitKind; declare_clippy_lint! { /// **What it does:** Checks for incompatible bit masks in comparisons. diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 07b4f572dd54..ccaa277efbda 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -4,13 +4,13 @@ use crate::utils::{ }; use if_chain::if_chain; use rustc::hir::map::Map; +use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use syntax::ast::LitKind; declare_clippy_lint! { /// **What it does:** Checks for boolean expressions that can be written more diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index e8168cb7393a..9c06eb962d7b 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -4,11 +4,11 @@ use crate::utils::{ }; use if_chain::if_chain; use rustc::ty; +use rustc_ast::ast::{Name, UintTy}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::{Name, UintTy}; declare_clippy_lint! { /// **What it does:** Checks for naive byte counts diff --git a/clippy_lints/src/cargo_common_metadata.rs b/clippy_lints/src/cargo_common_metadata.rs index 9e0e9d7dd6a0..06e866dd72a0 100644 --- a/clippy_lints/src/cargo_common_metadata.rs +++ b/clippy_lints/src/cargo_common_metadata.rs @@ -3,10 +3,10 @@ use std::path::PathBuf; use crate::utils::span_lint; +use rustc_ast::ast::Crate; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::DUMMY_SP; -use syntax::ast::Crate; declare_clippy_lint! { /// **What it does:** Checks to see if all common metadata is defined in diff --git a/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs index 835f8b7f902a..23992ae89a70 100644 --- a/clippy_lints/src/checked_conversions.rs +++ b/clippy_lints/src/checked_conversions.rs @@ -2,11 +2,11 @@ use if_chain::if_chain; use rustc::lint::in_external_macro; +use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::LitKind; use crate::utils::{snippet_with_applicability, span_lint_and_sugg, SpanlessEq}; diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs index ecae13a49708..d0f15d2373a7 100644 --- a/clippy_lints/src/cognitive_complexity.rs +++ b/clippy_lints/src/cognitive_complexity.rs @@ -1,13 +1,13 @@ //! calculate cognitive complexity and warn about overly complex functions use rustc::hir::map::Map; +use rustc_ast::ast::Attribute; use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use rustc_span::BytePos; -use syntax::ast::Attribute; use crate::utils::{match_type, paths, snippet_opt, span_lint_and_help, LimitStack}; diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index c6ca85b0cdf4..25fb773a6d67 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -13,9 +13,9 @@ //! This lint is **warn** by default use if_chain::if_chain; +use rustc_ast::ast; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast; use crate::utils::sugg::Sugg; use crate::utils::{snippet_block, snippet_block_with_applicability, span_lint_and_sugg, span_lint_and_then}; diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index edfd2486be28..9bb7b540d68f 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -5,6 +5,7 @@ use if_chain::if_chain; use rustc::ty::subst::{Subst, SubstsRef}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::{bug, span_bug}; +use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; use rustc_data_structures::sync::Lrc; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, QPath, UnOp}; @@ -13,7 +14,6 @@ use rustc_span::symbol::Symbol; use std::cmp::Ordering::{self, Equal}; use std::convert::TryInto; use std::hash::{Hash, Hasher}; -use syntax::ast::{FloatTy, LitFloatType, LitKind}; /// A `LitKind`-like enum to fold constant `Expr`s into. #[derive(Debug, Clone)] diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index eb785e4c3cb2..67f86f50ef61 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -1,10 +1,10 @@ use crate::utils::{snippet_opt, span_lint_and_help, span_lint_and_sugg}; +use rustc_ast::ast; +use rustc_ast::tokenstream::TokenStream; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use syntax::ast; -use syntax::tokenstream::TokenStream; declare_clippy_lint! { /// **What it does:** Checks for usage of dbg!() macro. diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index be65fd21a68e..89a68990c87e 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -3,6 +3,7 @@ use if_chain::if_chain; use itertools::Itertools; use rustc::lint::in_external_macro; use rustc::ty; +use rustc_ast::ast::{AttrKind, Attribute}; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; @@ -10,7 +11,6 @@ use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::{BytePos, MultiSpan, Span}; use rustc_span::Pos; use std::ops::Range; -use syntax::ast::{AttrKind, Attribute}; use url::Url; declare_clippy_lint! { @@ -251,8 +251,8 @@ fn lint_for_missing_headers<'a, 'tcx>( /// Cleanup documentation decoration (`///` and such). /// -/// We can't use `syntax::attr::AttributeMethods::with_desugared_doc` or -/// `syntax::parse::lexer::comments::strip_doc_comment_decoration` because we +/// We can't use `rustc_ast::attr::AttributeMethods::with_desugared_doc` or +/// `rustc_ast::parse::lexer::comments::strip_doc_comment_decoration` because we /// need to keep track of /// the spans but this function is inspired from the later. #[allow(clippy::cast_possible_truncation)] diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index c4c4758ebb78..7f2ff8b9b26f 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -1,7 +1,7 @@ use crate::utils::span_lint; +use rustc_ast::ast::{Expr, ExprKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::{Expr, ExprKind}; declare_clippy_lint! { /// **What it does:** Checks for unnecessary double parentheses. diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index c41c5aadbee7..ccaa35350cc2 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -1,9 +1,9 @@ //! Lint on if expressions with an else if, but without a final else branch. use rustc::lint::in_external_macro; +use rustc_ast::ast::{Expr, ExprKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::{Expr, ExprKind}; use crate::utils::span_lint_and_help; diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index e8063ac3006c..5bc8a446cf0a 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -5,11 +5,11 @@ use crate::consts::{miri_to_const, Constant}; use crate::utils::span_lint; use rustc::ty; use rustc::ty::util::IntTypeExt; +use rustc_ast::ast::{IntTy, UintTy}; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::convert::TryFrom; -use syntax::ast::{IntTy, UintTy}; declare_clippy_lint! { /// **What it does:** Checks for C-like enumerations that are diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 0d14b8a75e8a..882020a7adc7 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -2,11 +2,11 @@ use crate::utils::{camel_case, is_present_in_source}; use crate::utils::{span_lint, span_lint_and_help}; +use rustc_ast::ast::{EnumDef, Item, ItemKind, VisibilityKind}; use rustc_lint::{EarlyContext, EarlyLintPass, Lint}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; -use syntax::ast::{EnumDef, Item, ItemKind, VisibilityKind}; declare_clippy_lint! { /// **What it does:** Detects enumeration variants that are prefixed or suffixed diff --git a/clippy_lints/src/excessive_bools.rs b/clippy_lints/src/excessive_bools.rs index 71537d4a9f07..ddbc3c377a27 100644 --- a/clippy_lints/src/excessive_bools.rs +++ b/clippy_lints/src/excessive_bools.rs @@ -1,8 +1,8 @@ use crate::utils::{attr_by_name, in_macro, match_path_ast, span_lint_and_help}; +use rustc_ast::ast::{AssocItemKind, Extern, FnSig, Item, ItemKind, Ty, TyKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::Span; -use syntax::ast::{AssocItemKind, Extern, FnSig, Item, ItemKind, Ty, TyKind}; use std::convert::TryInto; diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index a3005d8bd82a..320121b27714 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -1,10 +1,10 @@ use crate::utils::{is_expn_of, match_function_call, paths, span_lint, span_lint_and_sugg}; use if_chain::if_chain; +use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::LitKind; declare_clippy_lint! { /// **What it does:** Checks for usage of `write!()` / `writeln()!` which can be diff --git a/clippy_lints/src/float_literal.rs b/clippy_lints/src/float_literal.rs index 18006f0534f0..30d4b25318f7 100644 --- a/clippy_lints/src/float_literal.rs +++ b/clippy_lints/src/float_literal.rs @@ -2,12 +2,12 @@ use crate::utils::span_lint_and_sugg; use crate::utils::sugg::format_numeric_literal; use if_chain::if_chain; use rustc::ty; +use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::{f32, f64, fmt}; -use syntax::ast::{FloatTy, LitFloatType, LitKind}; declare_clippy_lint! { /// **What it does:** Checks for float literals with a precision greater diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index eed4f58cf902..29f924ebe1c5 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -11,10 +11,10 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; +use rustc_ast::ast; use std::f32::consts as f32_consts; use std::f64::consts as f64_consts; use sugg::{format_numeric_literal, Sugg}; -use syntax::ast; declare_clippy_lint! { /// **What it does:** Looks for floating-point expressions that diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 6c80b6525bb5..10bc2f12f252 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -4,12 +4,12 @@ use crate::utils::{ walk_ptrs_ty, }; use if_chain::if_chain; +use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, MatchSource, PatKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use syntax::ast::LitKind; declare_clippy_lint! { /// **What it does:** Checks for the use of `format!("string literal with no diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 0ab6b1242b3f..a05f911c4c5e 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -1,10 +1,10 @@ use crate::utils::{differing_macro_contexts, snippet_opt, span_lint_and_help, span_lint_and_note}; use if_chain::if_chain; use rustc::lint::in_external_macro; +use rustc_ast::ast::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp}; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use syntax::ast::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp}; declare_clippy_lint! { /// **What it does:** Checks for use of the non-existent `=*`, `=!` and `=-` diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 620ec1f49510..e435b61bbbef 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -6,6 +6,7 @@ use crate::utils::{ use rustc::hir::map::Map; use rustc::lint::in_external_macro; use rustc::ty::{self, Ty}; +use rustc_ast::ast::Attribute; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir as hir; @@ -15,7 +16,6 @@ use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use rustc_target::spec::abi::Abi; -use syntax::ast::Attribute; declare_clippy_lint! { /// **What it does:** Checks for functions with too many parameters. diff --git a/clippy_lints/src/get_last_with_len.rs b/clippy_lints/src/get_last_with_len.rs index 19dd103247da..e4bad5ca5c51 100644 --- a/clippy_lints/src/get_last_with_len.rs +++ b/clippy_lints/src/get_last_with_len.rs @@ -2,13 +2,13 @@ use crate::utils::{is_type_diagnostic_item, snippet_with_applicability, span_lint_and_sugg, SpanlessEq}; use if_chain::if_chain; +use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; use rustc_span::symbol::Symbol; -use syntax::ast::LitKind; declare_clippy_lint! { /// **What it does:** Checks for using `x.get(x.len() - 1)` instead of diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index 4689e24f368e..9b6e243f5f04 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -2,9 +2,9 @@ //! on the condition use rustc::lint::in_external_macro; +use rustc_ast::ast::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::{BinOpKind, Expr, ExprKind, UnOp}; use crate::utils::span_lint_and_help; diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index f4a7b798521f..21444ffb23d7 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -3,10 +3,10 @@ use crate::consts::{constant, Constant}; use crate::utils::{higher, span_lint, span_lint_and_help}; use rustc::ty; +use rustc_ast::ast::RangeLimits; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::RangeLimits; declare_clippy_lint! { /// **What it does:** Checks for out of bounds array indexing with a constant diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index 85c61ba23964..de16a4f1ef82 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -2,11 +2,11 @@ use crate::utils::span_lint_and_then; use crate::utils::sugg::DiagnosticBuilderExt; +use rustc_ast::ast::{Attribute, Name}; use rustc_errors::Applicability; use rustc_hir::{TraitItem, TraitItemKind, TraitMethod}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::{Attribute, Name}; declare_clippy_lint! { /// **What it does:** Checks for `#[inline]` on trait methods without bodies diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index c6734427dab7..f2781b734cf6 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -1,9 +1,9 @@ //! lint on blocks unnecessarily using >= with a + 1 or - 1 +use rustc_ast::ast::{BinOpKind, Expr, ExprKind, Lit, LitKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::{BinOpKind, Expr, ExprKind, Lit, LitKind}; use crate::utils::{snippet_opt, span_lint_and_then}; diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index 13da725393b3..8d6a0212b5c1 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -2,9 +2,9 @@ use crate::utils::span_lint; use matches::matches; +use rustc_ast::ast::{Block, ItemKind, StmtKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::{Block, ItemKind, StmtKind}; declare_clippy_lint! { /// **What it does:** Checks for items declared after some statement in a block. diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 821ca2fefa4e..48881e1c2f03 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -1,5 +1,6 @@ use crate::utils::{get_item_name, snippet_with_applicability, span_lint, span_lint_and_sugg, walk_ptrs_ty}; use rustc::ty; +use rustc_ast::ast::{LitKind, Name}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; @@ -7,7 +8,6 @@ use rustc_hir::{AssocItemKind, BinOpKind, Expr, ExprKind, ImplItemRef, Item, Ite use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::{Span, Spanned}; -use syntax::ast::{LitKind, Name}; declare_clippy_lint! { /// **What it does:** Checks for getting the length of something via `.len()` diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c732657b2e57..8f05fe565cfb 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -19,6 +19,8 @@ extern crate fmt_macros; #[allow(unused_extern_crates)] extern crate rustc; #[allow(unused_extern_crates)] +extern crate rustc_ast; +#[allow(unused_extern_crates)] extern crate rustc_ast_pretty; #[allow(unused_extern_crates)] extern crate rustc_attr; @@ -50,8 +52,6 @@ extern crate rustc_span; extern crate rustc_target; #[allow(unused_extern_crates)] extern crate rustc_typeck; -#[allow(unused_extern_crates)] -extern crate syntax; use rustc::session::Session; use rustc_data_structures::fx::FxHashSet; @@ -318,7 +318,7 @@ pub mod zero_div_zero; pub use crate::utils::conf::Conf; mod reexport { - crate use syntax::ast::Name; + crate use rustc_ast::ast::Name; } /// Register all pre expansion lints @@ -341,7 +341,7 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, conf: &Co } #[doc(hidden)] -pub fn read_conf(args: &[syntax::ast::NestedMetaItem], sess: &Session) -> Conf { +pub fn read_conf(args: &[rustc_ast::ast::NestedMetaItem], sess: &Session) -> Conf { use std::path::Path; match utils::conf::file_from_args(args) { Ok(file_name) => { diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 7c8001eebd47..66435f954231 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -4,10 +4,10 @@ use crate::utils::{in_macro, snippet_opt, span_lint_and_sugg}; use if_chain::if_chain; use rustc::lint::in_external_macro; +use rustc_ast::ast::{Expr, ExprKind, Lit, LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; -use syntax::ast::{Expr, ExprKind, Lit, LitFloatType, LitIntType, LitKind}; declare_clippy_lint! { /// **What it does:** Warns if a long integral or floating-point constant does diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index eb15b104bea6..006281a1b5b5 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -15,6 +15,7 @@ use rustc::hir::map::Map; use rustc::lint::in_external_macro; use rustc::middle::region; use rustc::ty::{self, Ty}; +use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; @@ -31,7 +32,6 @@ use rustc_span::{BytePos, Symbol}; use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase}; use std::iter::{once, Iterator}; use std::mem; -use syntax::ast; declare_clippy_lint! { /// **What it does:** Checks for for-loops that manually copy items between diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index f96fb00acd04..72227555b259 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -4,12 +4,12 @@ use crate::utils::{ }; use if_chain::if_chain; use rustc::ty; +use rustc_ast::ast::Ident; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use syntax::ast::Ident; declare_clippy_lint! { /// **What it does:** Checks for usage of `iterator.map(|x| x.clone())` and suggests diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index d9d3611bc5a0..6f1efe0fd85c 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -10,6 +10,7 @@ use crate::utils::{ use if_chain::if_chain; use rustc::lint::in_external_macro; use rustc::ty::{self, Ty}; +use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::def::CtorKind; use rustc_hir::{ @@ -21,7 +22,6 @@ use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use std::cmp::Ordering; use std::collections::Bound; -use syntax::ast::LitKind; declare_clippy_lint! { /// **What it does:** Checks for matches with a single arm where an `if let` diff --git a/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/clippy_lints/src/methods/manual_saturating_arithmetic.rs index 19f3c4478616..aaed6d75048c 100644 --- a/clippy_lints/src/methods/manual_saturating_arithmetic.rs +++ b/clippy_lints/src/methods/manual_saturating_arithmetic.rs @@ -1,10 +1,10 @@ use crate::utils::{match_qpath, snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; +use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_target::abi::LayoutOf; -use syntax::ast; pub fn lint(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, args: &[&[hir::Expr<'_>]], arith: &str) { let unwrap_arg = &args[0][1]; diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 00a9fd894647..06fb9516456e 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -12,6 +12,7 @@ use matches::matches; use rustc::hir::map::Map; use rustc::lint::in_external_macro; use rustc::ty::{self, Predicate, Ty}; +use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; @@ -19,7 +20,6 @@ use rustc_lint::{LateContext, LateLintPass, Lint, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::symbol::{sym, Symbol, SymbolStr}; -use syntax::ast; use crate::consts::{constant, Constant}; use crate::utils::usage::mutated_variables; diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 85d66db83b15..6618876b3751 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -1,6 +1,7 @@ use if_chain::if_chain; use matches::matches; use rustc::ty; +use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{ @@ -10,7 +11,6 @@ use rustc_hir::{ use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::{ExpnKind, Span}; -use syntax::ast::LitKind; use crate::consts::{constant, Constant}; use crate::utils::sugg::Sugg; diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 6e89f35143be..60b672766231 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -4,16 +4,16 @@ use crate::utils::{ }; use if_chain::if_chain; use rustc::lint::in_external_macro; +use rustc_ast::ast::{ + Block, Expr, ExprKind, GenericParamKind, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind, + StmtKind, UnOp, +}; +use rustc_ast::visit::{walk_expr, FnKind, Visitor}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use syntax::ast::{ - Block, Expr, ExprKind, GenericParamKind, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind, - StmtKind, UnOp, -}; -use syntax::visit::{walk_expr, FnKind, Visitor}; declare_clippy_lint! { /// **What it does:** Checks for structure field patterns bound to wildcards. diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index e502db59e66b..5e32172d78a1 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -8,12 +8,12 @@ use crate::utils::span_lint; use if_chain::if_chain; use rustc::ty; +use rustc_ast::ast::{self, MetaItem, MetaItemKind}; +use rustc_ast::attr; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; -use syntax::ast::{self, MetaItem, MetaItemKind}; -use syntax::attr; declare_clippy_lint! { /// **What it does:** Warns if there is missing doc for any documentable item diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index 407321effb80..b736c58879ba 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -1,9 +1,9 @@ use crate::utils::span_lint; +use rustc_ast::ast; use rustc_hir as hir; use rustc_lint::{self, LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use syntax::ast; declare_clippy_lint! { /// **What it does:** it lints if an exported function, method, trait method with default impl, diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index 0bcce04e8120..88605c52f2e2 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -1,10 +1,10 @@ //! lint on multiple versions of a crate being used use crate::utils::span_lint; +use rustc_ast::ast::Crate; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::DUMMY_SP; -use syntax::ast::Crate; use itertools::Itertools; diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 98cb9126f8ba..bbd2e4d83faa 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -4,10 +4,10 @@ use crate::utils::{match_type, paths, span_lint}; use rustc::ty::{self, Ty}; +use rustc_ast::ast; use rustc_hir::Expr; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast; declare_clippy_lint! { /// **What it does:** Checks for usages of `Mutex` where an atomic will do. diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 7282874fdbd0..4c00d15538ff 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -4,12 +4,12 @@ use crate::utils::sugg::Sugg; use crate::utils::{higher, parent_node_is_if_expr, span_lint, span_lint_and_sugg}; +use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; -use syntax::ast::LitKind; declare_clippy_lint! { /// **What it does:** Checks for expressions of the form `if c { true } else { diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 660aae25f557..6be4b1effeae 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -33,11 +33,11 @@ //! ``` //! //! This lint is **warn** by default. +use rustc_ast::ast; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::{original_sp, DUMMY_SP}; use rustc_span::Span; -use syntax::ast; use crate::utils::{indent_of, snippet, snippet_block, span_lint_and_help}; diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 10782b9f3b4d..01343341726a 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -6,6 +6,7 @@ use crate::utils::{ use if_chain::if_chain; use matches::matches; use rustc::ty::{self, TypeFoldable}; +use rustc_ast::ast::Attribute; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir::intravisit::FnKind; @@ -19,7 +20,6 @@ use rustc_span::{Span, Symbol}; use rustc_target::spec::abi::Abi; use rustc_typeck::expr_use_visitor as euv; use std::borrow::Cow; -use syntax::ast::Attribute; declare_clippy_lint! { /// **What it does:** Checks for functions taking arguments by value, but not diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index cb3e9ccba1e4..847eb0eaf025 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -1,14 +1,14 @@ use crate::utils::{span_lint, span_lint_and_then}; +use rustc_ast::ast::{ + Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, Ident, Item, ItemKind, Local, Mac, Pat, PatKind, +}; +use rustc_ast::attr; +use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor}; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use rustc_span::symbol::SymbolStr; use std::cmp::Ordering; -use syntax::ast::{ - Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, Ident, Item, ItemKind, Local, Mac, Pat, PatKind, -}; -use syntax::attr; -use syntax::visit::{walk_block, walk_expr, walk_pat, Visitor}; declare_clippy_lint! { /// **What it does:** Checks for names that are very similar and thus confusing. diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index ff0cb53509d9..9d3b67988dbb 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -1,9 +1,9 @@ use crate::utils::{match_type, paths, span_lint, walk_ptrs_ty}; +use rustc_ast::ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::{Span, Spanned}; -use syntax::ast::LitKind; declare_clippy_lint! { /// **What it does:** Checks for duplicate open options as well as combinations diff --git a/clippy_lints/src/option_env_unwrap.rs b/clippy_lints/src/option_env_unwrap.rs index 6dc6893bf71c..96ab4238008d 100644 --- a/clippy_lints/src/option_env_unwrap.rs +++ b/clippy_lints/src/option_env_unwrap.rs @@ -1,8 +1,8 @@ use crate::utils::{is_direct_expn_of, span_lint_and_help}; use if_chain::if_chain; +use rustc_ast::ast::{Expr, ExprKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::{Expr, ExprKind}; declare_clippy_lint! { /// **What it does:** Checks for usage of `option_env!(...).unwrap()` and diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index 76a77e25de3c..2cd9200ddb25 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -1,10 +1,10 @@ use crate::utils::{is_direct_expn_of, is_expn_of, match_function_call, paths, span_lint}; use if_chain::if_chain; +use rustc_ast::ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::Span; -use syntax::ast::LitKind; declare_clippy_lint! { /// **What it does:** Checks for missing parameters in `panic!`. diff --git a/clippy_lints/src/path_buf_push_overwrite.rs b/clippy_lints/src/path_buf_push_overwrite.rs index 775a8ad0b933..bdbaf2695c8e 100644 --- a/clippy_lints/src/path_buf_push_overwrite.rs +++ b/clippy_lints/src/path_buf_push_overwrite.rs @@ -1,11 +1,11 @@ use crate::utils::{match_type, paths, span_lint_and_sugg, walk_ptrs_ty}; use if_chain::if_chain; +use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::path::{Component, Path}; -use syntax::ast::LitKind; declare_clippy_lint! { /// **What it does:*** Checks for [push](https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.push) diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index 8ba4e10c9660..8b6d0336b207 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -1,9 +1,9 @@ use crate::utils::{snippet_with_applicability, span_lint_and_sugg}; +use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind, UnOp}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; -use syntax::ast::{BinOpKind, Expr, ExprKind, LitKind, UnOp}; declare_clippy_lint! { /// **What it does:** Checks for operations where precedence may be unclear @@ -123,7 +123,7 @@ fn is_arith_expr(expr: &Expr) -> bool { #[must_use] fn is_bit_op(op: BinOpKind) -> bool { - use syntax::ast::BinOpKind::{BitAnd, BitOr, BitXor, Shl, Shr}; + use rustc_ast::ast::BinOpKind::{BitAnd, BitOr, BitXor, Shl, Shr}; match op { BitXor | BitAnd | BitOr | Shl | Shr => true, _ => false, @@ -132,7 +132,7 @@ fn is_bit_op(op: BinOpKind) -> bool { #[must_use] fn is_arith_op(op: BinOpKind) -> bool { - use syntax::ast::BinOpKind::{Add, Div, Mul, Rem, Sub}; + use rustc_ast::ast::BinOpKind::{Add, Div, Mul, Rem, Sub}; match op { Add | Sub | Mul | Div | Rem => true, _ => false, diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index f1a93d508ce2..c9de88d9c83d 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -1,10 +1,10 @@ use if_chain::if_chain; +use rustc_ast::ast::RangeLimits; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; -use syntax::ast::RangeLimits; use crate::utils::sugg::Sugg; use crate::utils::{higher, SpanlessEq}; diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index a839a023e525..b12c3c344ef4 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -1,8 +1,8 @@ use crate::utils::span_lint_and_sugg; +use rustc_ast::ast::{Expr, ExprKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::{Expr, ExprKind}; declare_clippy_lint! { /// **What it does:** Checks for fields in struct literals where shorthands diff --git a/clippy_lints/src/redundant_pattern_matching.rs b/clippy_lints/src/redundant_pattern_matching.rs index c8706c2b363b..a0b584b57ef3 100644 --- a/clippy_lints/src/redundant_pattern_matching.rs +++ b/clippy_lints/src/redundant_pattern_matching.rs @@ -1,9 +1,9 @@ use crate::utils::{match_qpath, paths, snippet, span_lint_and_then}; +use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Arm, Expr, ExprKind, MatchSource, PatKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::LitKind; declare_clippy_lint! { /// **What it does:** Lint for redundant pattern matching over `Result` or diff --git a/clippy_lints/src/redundant_static_lifetimes.rs b/clippy_lints/src/redundant_static_lifetimes.rs index feb045f9c152..4a7a15aba5be 100644 --- a/clippy_lints/src/redundant_static_lifetimes.rs +++ b/clippy_lints/src/redundant_static_lifetimes.rs @@ -1,8 +1,8 @@ use crate::utils::{snippet, span_lint_and_then}; +use rustc_ast::ast::{Item, ItemKind, Ty, TyKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::{Item, ItemKind, Ty, TyKind}; declare_clippy_lint! { /// **What it does:** Checks for constants and statics with an explicit `'static` lifetime. diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index c575ef67f2a9..d5797468e9d5 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -1,9 +1,9 @@ use crate::utils::{in_macro, snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; +use rustc_ast::ast::{Expr, ExprKind, UnOp}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::{Expr, ExprKind, UnOp}; declare_clippy_lint! { /// **What it does:** Checks for usage of `*&` and `*&mut` in expressions. diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 028b89b39b94..4bcb9198792d 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -1,13 +1,13 @@ use crate::consts::{constant, Constant}; use crate::utils::{is_expn_of, match_def_path, match_type, paths, span_lint, span_lint_and_help}; use if_chain::if_chain; +use rustc_ast::ast::{LitKind, StrStyle}; use rustc_data_structures::fx::FxHashSet; use rustc_hir::{Block, BorrowKind, Crate, Expr, ExprKind, HirId}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::{BytePos, Span}; use std::convert::TryFrom; -use syntax::ast::{LitKind, StrStyle}; declare_clippy_lint! { /// **What it does:** Checks [regex](https://crates.io/crates/regex) creation diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index fc371dccd732..ef1bbfd8fa92 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -1,12 +1,12 @@ use if_chain::if_chain; use rustc::lint::in_external_macro; +use rustc_ast::ast; +use rustc_ast::visit::FnKind; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::BytePos; -use syntax::ast; -use syntax::visit::FnKind; use crate::utils::{in_macro, match_path_ast, snippet_opt, span_lint_and_then}; diff --git a/clippy_lints/src/single_component_path_imports.rs b/clippy_lints/src/single_component_path_imports.rs index 5a9bc73fe42b..8d767a7fec88 100644 --- a/clippy_lints/src/single_component_path_imports.rs +++ b/clippy_lints/src/single_component_path_imports.rs @@ -1,10 +1,10 @@ use crate::utils::{in_macro, span_lint_and_sugg}; use if_chain::if_chain; +use rustc_ast::ast::{Item, ItemKind, UseTreeKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::edition::Edition; -use syntax::ast::{Item, ItemKind, UseTreeKind}; declare_clippy_lint! { /// **What it does:** Checking for imports with single component use path. diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index 71fcff33544e..8d8dbe0e4083 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -2,13 +2,13 @@ use crate::utils::sugg::Sugg; use crate::utils::{get_enclosing_block, match_qpath, span_lint_and_then, SpanlessEq}; use if_chain::if_chain; use rustc::hir::map::Map; +use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, NestedVisitorMap, Visitor}; use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, Lint}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::Symbol; -use syntax::ast::LitKind; declare_clippy_lint! { /// **What it does:** Checks slow zero-filled vector initialization diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 20ed4d9aac05..e777adb22cfb 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -153,7 +153,7 @@ declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) { use crate::utils::{snippet, snippet_with_applicability}; - use syntax::ast::LitKind; + use rustc_ast::ast::LitKind; if_chain! { if let ExprKind::MethodCall(path, _, args) = &e.kind; diff --git a/clippy_lints/src/tabs_in_doc_comments.rs b/clippy_lints/src/tabs_in_doc_comments.rs index 41e3f9918cc9..7b673e15b764 100644 --- a/clippy_lints/src/tabs_in_doc_comments.rs +++ b/clippy_lints/src/tabs_in_doc_comments.rs @@ -1,10 +1,10 @@ use crate::utils::span_lint_and_sugg; +use rustc_ast::ast; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::{BytePos, Span}; use std::convert::TryFrom; -use syntax::ast; declare_clippy_lint! { /// **What it does:** Checks doc comments for usage of tab characters. diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 68c924cea475..4d1996ffcefb 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -3,12 +3,12 @@ use crate::utils::{ }; use if_chain::if_chain; use rustc::ty::{self, Ty}; +use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, GenericArg, Mutability, QPath, TyKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::borrow::Cow; -use syntax::ast; declare_clippy_lint! { /// **What it does:** Checks for transmutes that can't ever be correct on any diff --git a/clippy_lints/src/transmuting_null.rs b/clippy_lints/src/transmuting_null.rs index dcab84122505..494dd4486891 100644 --- a/clippy_lints/src/transmuting_null.rs +++ b/clippy_lints/src/transmuting_null.rs @@ -2,10 +2,10 @@ use crate::consts::{constant_context, Constant}; use crate::utils::{match_qpath, paths, span_lint}; use if_chain::if_chain; use rustc::lint::in_external_macro; +use rustc_ast::ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::LitKind; declare_clippy_lint! { /// **What it does:** Checks for transmute calls which would receive a null pointer. diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index e9c0b0935fa9..f90867605aa1 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -9,6 +9,7 @@ use rustc::hir::map::Map; use rustc::lint::in_external_macro; use rustc::ty::layout::LayoutOf; use rustc::ty::{self, InferTy, Ty, TyCtxt, TypeckTables}; +use rustc_ast::ast::{FloatTy, IntTy, LitFloatType, LitIntType, LitKind, UintTy}; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; @@ -24,7 +25,6 @@ use rustc_span::source_map::Span; use rustc_span::symbol::{sym, Symbol}; use rustc_target::spec::abi::Abi; use rustc_typeck::hir_ty_to_ty; -use syntax::ast::{FloatTy, IntTy, LitFloatType, LitIntType, LitKind, UintTy}; use crate::consts::{constant, Constant}; use crate::utils::paths; diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index 355d2ec0f1c7..d073c197656c 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -1,10 +1,10 @@ use crate::utils::{is_allowed, snippet, span_lint_and_sugg}; +use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, HirId}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use syntax::ast::LitKind; use unicode_normalization::UnicodeNormalization; declare_clippy_lint! { diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 2b2df4241505..86c469a4dccf 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -1,9 +1,9 @@ use crate::utils::span_lint; +use rustc_ast::ast::{Ident, Item, ItemKind, UseTree, UseTreeKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::symbol::SymbolStr; -use syntax::ast::{Ident, Item, ItemKind, UseTree, UseTreeKind}; declare_clippy_lint! { /// **What it does:** Checks for imports that remove "unsafe" from an item's diff --git a/clippy_lints/src/utils/attrs.rs b/clippy_lints/src/utils/attrs.rs index 8f886d174f1e..3721350959b9 100644 --- a/clippy_lints/src/utils/attrs.rs +++ b/clippy_lints/src/utils/attrs.rs @@ -1,7 +1,7 @@ use rustc::session::Session; +use rustc_ast::ast; use rustc_errors::Applicability; use std::str::FromStr; -use syntax::ast; /// Deprecation status of attributes known by Clippy. #[allow(dead_code)] diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index a4dc24cecc22..e2a19d633b3e 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -4,14 +4,14 @@ use crate::utils::{get_attr, higher}; use rustc::hir::map::Map; use rustc::session::Session; +use rustc_ast::ast::{Attribute, LitFloatType, LitKind}; +use rustc_ast::walk_list; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::intravisit::{NestedVisitorMap, Visitor}; use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, Pat, PatKind, QPath, Stmt, StmtKind, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::{Attribute, LitFloatType, LitKind}; -use syntax::walk_list; declare_clippy_lint! { /// **What it does:** Generates clippy code that detects the offending pattern diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 584cde2678f3..a1d7bebc7b56 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -3,12 +3,12 @@ #![deny(clippy::missing_docs_in_private_items)] use lazy_static::lazy_static; +use rustc_ast::ast::{LitKind, MetaItemKind, NestedMetaItem}; use rustc_span::source_map; use source_map::Span; use std::path::{Path, PathBuf}; use std::sync::Mutex; use std::{env, fmt, fs, io}; -use syntax::ast::{LitKind, MetaItemKind, NestedMetaItem}; /// Gets the configuration file from arguments. pub fn file_from_args(args: &[NestedMetaItem]) -> Result, (&'static str, Span)> { diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index b046d7dc08f1..f27cc57fb545 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -6,9 +6,9 @@ use crate::utils::{is_expn_of, match_def_path, match_qpath, paths}; use if_chain::if_chain; use rustc::ty; +use rustc_ast::ast; use rustc_hir as hir; use rustc_lint::LateContext; -use syntax::ast; /// Converts a hir binary operator to the corresponding `ast` type. #[must_use] diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index c62f95cd5624..dcdec2e7eb6a 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -2,6 +2,7 @@ use crate::consts::{constant_context, constant_simple}; use crate::utils::differing_macro_contexts; use rustc::ich::StableHashingContextProvider; use rustc::ty::TypeckTables; +use rustc_ast::ast::Name; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::{ BinOpKind, Block, BlockCheckMode, BodyId, BorrowKind, CaptureBy, Expr, ExprKind, Field, FnRetTy, GenericArg, @@ -10,7 +11,6 @@ use rustc_hir::{ }; use rustc_lint::LateContext; use std::hash::Hash; -use syntax::ast::Name; /// Type used to check whether two ast are the same. This is different from the /// operator diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index aa76ada7b484..a2a4dc4201b0 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -2,11 +2,11 @@ use crate::utils::get_attr; use rustc::session::Session; +use rustc_ast::ast::Attribute; use rustc_hir as hir; use rustc_hir::print; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::Attribute; declare_clippy_lint! { /// **What it does:** Dumps every ast/hir node which has the `#[clippy::dump]` diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 85fee84cb3b9..c348f5794b9c 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -4,6 +4,8 @@ use crate::utils::{ }; use if_chain::if_chain; use rustc::hir::map::Map; +use rustc_ast::ast::{Crate as AstCrate, ItemKind, LitKind, Name, NodeId}; +use rustc_ast::visit::FnKind; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir as hir; @@ -14,8 +16,6 @@ use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::{Span, Spanned}; use rustc_span::symbol::SymbolStr; -use syntax::ast::{Crate as AstCrate, ItemKind, LitKind, Name, NodeId}; -use syntax::visit::FnKind; declare_clippy_lint! { /// **What it does:** Checks for various things we like to keep tidy in clippy. diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 708e3feef293..640cce113806 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -33,6 +33,7 @@ use rustc::ty::{ subst::GenericArg, Binder, Ty, TyCtxt, }; +use rustc_ast::ast::{self, Attribute, LitKind}; use rustc_attr as attr; use rustc_errors::Applicability; use rustc_hir as hir; @@ -52,7 +53,6 @@ use rustc_span::source_map::original_sp; use rustc_span::symbol::{self, kw, Symbol}; use rustc_span::{BytePos, Pos, Span, DUMMY_SP}; use smallvec::SmallVec; -use syntax::ast::{self, Attribute, LitKind}; use crate::consts::{constant, Constant}; use crate::reexport::Name; diff --git a/clippy_lints/src/utils/ptr.rs b/clippy_lints/src/utils/ptr.rs index 3d97c18e9b4e..176edcf1652f 100644 --- a/clippy_lints/src/utils/ptr.rs +++ b/clippy_lints/src/utils/ptr.rs @@ -1,11 +1,11 @@ use crate::utils::{get_pat_name, match_var, snippet}; use rustc::hir::map::Map; +use rustc_ast::ast::Name; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::{Body, BodyId, Expr, ExprKind, Param}; use rustc_lint::LateContext; use rustc_span::source_map::Span; use std::borrow::Cow; -use syntax::ast::Name; pub fn get_spans( cx: &LateContext<'_, '_>, diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 278505859b72..05cc4f33eaed 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -3,6 +3,8 @@ use crate::utils::{higher, snippet, snippet_opt, snippet_with_macro_callsite}; use matches::matches; +use rustc_ast::util::parser::AssocOp; +use rustc_ast::{ast, token}; use rustc_ast_pretty::pprust::token_kind_to_string; use rustc_errors::Applicability; use rustc_hir as hir; @@ -12,8 +14,6 @@ use rustc_span::{BytePos, Pos}; use std::borrow::Cow; use std::convert::TryInto; use std::fmt::Display; -use syntax::util::parser::AssocOp; -use syntax::{ast, token}; pub use crate::literal_representation::format_numeric_literal; @@ -132,7 +132,7 @@ impl<'a> Sugg<'a> { /// Prepare a suggestion from an expression. pub fn ast(cx: &EarlyContext<'_>, expr: &ast::Expr, default: &'a str) -> Self { - use syntax::ast::RangeLimits; + use rustc_ast::ast::RangeLimits; let snippet = snippet(cx, expr.span, default); @@ -426,7 +426,7 @@ enum Associativity { /// associative. #[must_use] fn associativity(op: &AssocOp) -> Associativity { - use syntax::util::parser::AssocOp::{ + use rustc_ast::util::parser::AssocOp::{ Add, As, Assign, AssignOp, BitAnd, BitOr, BitXor, Colon, Divide, DotDot, DotDotEq, Equal, Greater, GreaterEqual, LAnd, LOr, Less, LessEqual, Modulus, Multiply, NotEqual, ShiftLeft, ShiftRight, Subtract, }; @@ -442,7 +442,7 @@ fn associativity(op: &AssocOp) -> Associativity { /// Converts a `hir::BinOp` to the corresponding assigning binary operator. fn hirbinop2assignop(op: hir::BinOp) -> AssocOp { - use syntax::token::BinOpToken::{And, Caret, Minus, Or, Percent, Plus, Shl, Shr, Slash, Star}; + use rustc_ast::token::BinOpToken::{And, Caret, Minus, Or, Percent, Plus, Shl, Shr, Slash, Star}; AssocOp::AssignOp(match op.node { hir::BinOpKind::Add => Plus, @@ -469,10 +469,10 @@ fn hirbinop2assignop(op: hir::BinOp) -> AssocOp { /// Converts an `ast::BinOp` to the corresponding assigning binary operator. fn astbinop2assignop(op: ast::BinOp) -> AssocOp { - use syntax::ast::BinOpKind::{ + use rustc_ast::ast::BinOpKind::{ Add, And, BitAnd, BitOr, BitXor, Div, Eq, Ge, Gt, Le, Lt, Mul, Ne, Or, Rem, Shl, Shr, Sub, }; - use syntax::token::BinOpToken; + use rustc_ast::token::BinOpToken; AssocOp::AssignOp(match op.node { Add => BinOpToken::Plus, diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs index 3e8b29295f39..5871cf45ef90 100644 --- a/clippy_lints/src/utils/usage.rs +++ b/clippy_lints/src/utils/usage.rs @@ -1,6 +1,7 @@ use crate::utils::match_var; use rustc::hir::map::Map; use rustc::ty; +use rustc_ast::ast; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; @@ -9,7 +10,6 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_span::symbol::Ident; use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase}; -use syntax::ast; /// Returns a set of mutated local variable IDs, or `None` if mutations could not be determined. pub fn mutated_variables<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &'a LateContext<'a, 'tcx>) -> Option> { diff --git a/clippy_lints/src/wildcard_dependencies.rs b/clippy_lints/src/wildcard_dependencies.rs index 0be168d563ab..035a10b1a247 100644 --- a/clippy_lints/src/wildcard_dependencies.rs +++ b/clippy_lints/src/wildcard_dependencies.rs @@ -1,8 +1,8 @@ use crate::utils::span_lint; +use rustc_ast::ast::Crate; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::DUMMY_SP; -use syntax::ast::Crate; use if_chain::if_chain; diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 904e2fab07ad..d9fb9d444cb1 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -2,6 +2,9 @@ use std::borrow::Cow; use std::ops::Range; use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_sugg, span_lint_and_then}; +use rustc_ast::ast::{Expr, ExprKind, Mac, StrLit, StrStyle}; +use rustc_ast::token; +use rustc_ast::tokenstream::TokenStream; use rustc_errors::Applicability; use rustc_lexer::unescape::{self, EscapeError}; use rustc_lint::{EarlyContext, EarlyLintPass}; @@ -9,9 +12,6 @@ use rustc_parse::parser; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::Symbol; use rustc_span::{BytePos, Span}; -use syntax::ast::{Expr, ExprKind, Mac, StrLit, StrStyle}; -use syntax::token; -use syntax::tokenstream::TokenStream; declare_clippy_lint! { /// **What it does:** This lint warns when you use `println!("")` to From 78dc48ea501873ca4f9b4ce5b3049ec39703ee49 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 1 Mar 2020 23:32:49 +0900 Subject: [PATCH 153/243] Rustup to rust-lang/rust#69579 --- clippy_lints/src/write.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index d9fb9d444cb1..c59799fa1cf3 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -349,7 +349,7 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O if let Piece::NextArgument(arg) = piece { if arg.format.ty == "?" { // FIXME: modify rustc's fmt string parser to give us the current span - span_lint(cx, USE_DEBUG, parser.prev_span, "use of `Debug`-based formatting"); + span_lint(cx, USE_DEBUG, parser.prev_token.span, "use of `Debug`-based formatting"); } args.push(arg); } From cda7881869e6c96ae5b7839d2536e97c6127ef26 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 2 Mar 2020 00:17:14 +0900 Subject: [PATCH 154/243] Disable rls test for now --- .github/workflows/clippy_bors.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index a4f7b64cb6a7..ec192de191b1 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -231,7 +231,8 @@ jobs: matrix: integration: - 'rust-lang/cargo' - - 'rust-lang/rls' + # FIXME: Re-enable once we can test with rls again. + # - 'rust-lang/rls' - 'rust-lang/chalk' - 'rust-lang/rustfmt' - 'Marwes/combine' From 0a6d29940979aeb6bed98dcce67c4faa4e9df312 Mon Sep 17 00:00:00 2001 From: JarredAllen Date: Sun, 1 Mar 2020 13:12:56 -0800 Subject: [PATCH 155/243] Fixed compile error from merging --- clippy_lints/src/floating_point_arithmetic.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 6a6583f66102..b3b81ddb57c9 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -11,11 +11,10 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; -use rustc_ast::ast; +use rustc_ast::ast::{self, FloatTy, LitFloatType, LitKind}; use std::f32::consts as f32_consts; use std::f64::consts as f64_consts; use sugg::{format_numeric_literal, Sugg}; -use syntax::ast::{self, FloatTy, LitFloatType, LitKind}; declare_clippy_lint! { /// **What it does:** Looks for floating-point expressions that From d88750371dcd333482037dd87cfaaddd1b301685 Mon Sep 17 00:00:00 2001 From: JarredAllen Date: Sun, 1 Mar 2020 22:37:37 -0800 Subject: [PATCH 156/243] Refactor suggested by krishna-veerareddy --- clippy_lints/src/floating_point_arithmetic.rs | 149 ++++++++---------- 1 file changed, 65 insertions(+), 84 deletions(-) diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index b3b81ddb57c9..f2e6bd7da176 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -420,103 +420,84 @@ fn is_zero(expr: &Expr<'_>) -> bool { } } -fn check_custom_abs(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { - if let Some((cond, body, Some(else_body))) = higher::if_block(&expr) { +/// If the expressions are not opposites, return None +/// Otherwise, return true if expr2 = -expr1, false if expr1 = -expr2 and return the positive +/// expression +fn are_opposites<'a>( + cx: &LateContext<'_, '_>, + expr1: &'a Expr<'a>, + expr2: &'a Expr<'a>, +) -> Option<(bool, &'a Expr<'a>)> { + if let ExprKind::Block( + Block { + stmts: [], + expr: Some(expr1_inner), + .. + }, + _, + ) = &expr1.kind + { if let ExprKind::Block( Block { stmts: [], - expr: - Some(Expr { - kind: ExprKind::Unary(UnOp::UnNeg, else_expr), - .. - }), + expr: Some(expr2_inner), .. }, _, - ) = else_body.kind + ) = &expr2.kind { - if let ExprKind::Block( - Block { - stmts: [], - expr: Some(body), - .. - }, - _, - ) = &body.kind - { - if are_exprs_equal(cx, else_expr, body) { - if is_testing_positive(cx, cond, body) { - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "This looks like you've implemented your own absolute value function", - "try", - format!("{}.abs()", Sugg::hir(cx, body, "..")), - Applicability::MachineApplicable, - ); - } else if is_testing_negative(cx, cond, body) { - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "This looks like you've implemented your own negative absolute value function", - "try", - format!("-{}.abs()", Sugg::hir(cx, body, "..")), - Applicability::MachineApplicable, - ); - } + if let ExprKind::Unary(UnOp::UnNeg, expr1_neg) = &expr1_inner.kind { + if are_exprs_equal(cx, expr1_neg, expr2_inner) { + return Some((false, expr2_inner)); } } - } - if let ExprKind::Block( - Block { - stmts: [], - expr: - Some(Expr { - kind: ExprKind::Unary(UnOp::UnNeg, else_expr), - .. - }), - .. - }, - _, - ) = &body.kind - { - if let ExprKind::Block( - Block { - stmts: [], - expr: Some(body), - .. - }, - _, - ) = &else_body.kind - { - if are_exprs_equal(cx, else_expr, body) { - if is_testing_negative(cx, cond, body) { - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "This looks like you've implemented your own absolute value function", - "try", - format!("{}.abs()", Sugg::hir(cx, body, "..")), - Applicability::MachineApplicable, - ); - } else if is_testing_positive(cx, cond, body) { - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "This looks like you've implemented your own negative absolute value function", - "try", - format!("-{}.abs()", Sugg::hir(cx, body, "..")), - Applicability::MachineApplicable, - ); - } + if let ExprKind::Unary(UnOp::UnNeg, expr2_neg) = &expr2_inner.kind { + if are_exprs_equal(cx, expr1_inner, expr2_neg) { + return Some((true, expr1_inner)); } } } } + None +} + +fn check_custom_abs(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { + if let Some((cond, body, Some(else_body))) = higher::if_block(&expr) { + if let Some((expr1_pos, body)) = are_opposites(cx, body, else_body) { + let pos_abs_sugg = ( + "This looks like you've implemented your own absolute value function", + format!("{}.abs()", Sugg::hir(cx, body, "..")), + ); + let neg_abs_sugg = ( + "This looks like you've implemented your own negative absolute value function", + format!("-{}.abs()", Sugg::hir(cx, body, "..")), + ); + let sugg = if is_testing_positive(cx, cond, body) { + if expr1_pos { + pos_abs_sugg + } else { + neg_abs_sugg + } + } else if is_testing_negative(cx, cond, body) { + if expr1_pos { + neg_abs_sugg + } else { + pos_abs_sugg + } + } else { + return; + }; + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + sugg.0, + "try", + sugg.1, + Applicability::MachineApplicable, + ); + } + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic { From 0d584f3ff760b14c8b23ae52f8ae7631305e43af Mon Sep 17 00:00:00 2001 From: JarredAllen Date: Sun, 1 Mar 2020 23:11:29 -0800 Subject: [PATCH 157/243] Fix one last test issue --- clippy_lints/src/floating_point_arithmetic.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index f2e6bd7da176..de2c245f451d 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -76,12 +76,12 @@ declare_clippy_lint! { /// -a /// } else { /// a - /// } + /// }; /// let _ = if a < 0.0 { /// a /// } else { /// -a - /// } + /// }; /// ``` /// /// is better expressed as From 8669be56c48a26d730577fb5e77025172cfdfc44 Mon Sep 17 00:00:00 2001 From: mlegner Date: Mon, 2 Mar 2020 10:22:05 +0100 Subject: [PATCH 158/243] Whitelist unused attribute for use items. --- clippy_lints/src/attrs.rs | 1 + tests/ui/useless_attribute.fixed | 4 ++++ tests/ui/useless_attribute.rs | 4 ++++ tests/ui/useless_attribute.stderr | 2 +- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index f753d3dc1c7b..7d5e1d881912 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -248,6 +248,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Attributes { if is_word(lint, sym!(unused_imports)) || is_word(lint, sym!(deprecated)) || is_word(lint, sym!(unreachable_pub)) + || is_word(lint, sym!(unused)) { return; } diff --git a/tests/ui/useless_attribute.fixed b/tests/ui/useless_attribute.fixed index 56811a998728..ff626ab3ddfa 100644 --- a/tests/ui/useless_attribute.fixed +++ b/tests/ui/useless_attribute.fixed @@ -20,6 +20,10 @@ extern crate proc_macro_derive; #[allow(unused_imports)] use std::collections; +// don't lint on unused for `use` items +#[allow(unused)] +use std::option; + // don't lint on deprecated for `use` items mod foo { #[deprecated] diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index bbf5e495db4a..822c6b6ea068 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -20,6 +20,10 @@ extern crate proc_macro_derive; #[allow(unused_imports)] use std::collections; +// don't lint on unused for `use` items +#[allow(unused)] +use std::option; + // don't lint on deprecated for `use` items mod foo { #[deprecated] diff --git a/tests/ui/useless_attribute.stderr b/tests/ui/useless_attribute.stderr index 08a211b41a91..57ba976730c1 100644 --- a/tests/ui/useless_attribute.stderr +++ b/tests/ui/useless_attribute.stderr @@ -13,7 +13,7 @@ LL | #[cfg_attr(feature = "cargo-clippy", allow(dead_code))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(feature = "cargo-clippy", allow(dead_code)` error: useless lint attribute - --> $DIR/useless_attribute.rs:49:5 + --> $DIR/useless_attribute.rs:53:5 | LL | #[allow(clippy::almost_swapped)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(clippy::almost_swapped)]` From f1d0791c3a4d136300b483356a502fb873be31e1 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 3 Mar 2020 04:37:39 +0900 Subject: [PATCH 159/243] Rustup to rust-lang/rust#69469 --- clippy_lints/src/non_copy_const.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 46e26b326971..908d1fe286d4 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -128,7 +128,7 @@ fn verify_ty_bound<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, source: S db.span_label(const_kw_span, "make this a static item (maybe with lazy_static)"); }, Source::Assoc { ty: ty_span, .. } => { - if ty.flags.contains(TypeFlags::HAS_FREE_LOCAL_NAMES) { + if ty.flags.intersects(TypeFlags::HAS_FREE_LOCAL_NAMES) { db.span_label(ty_span, &format!("consider requiring `{}` to be `Copy`", ty)); } }, From a628733adeeab998fd8d455a0c872082813b43f1 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 14 Jan 2020 16:28:08 +0100 Subject: [PATCH 160/243] Don't lint debug formatting in debug impl --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/write.rs | 276 +++++++++++++++++++++----------------- 2 files changed, 157 insertions(+), 121 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 8f05fe565cfb..4157d33079ca 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -330,7 +330,7 @@ mod reexport { /// /// Used in `./src/driver.rs`. pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, conf: &Conf) { - store.register_pre_expansion_pass(|| box write::Write); + store.register_pre_expansion_pass(|| box write::Write::default()); store.register_pre_expansion_pass(|| box redundant_field_names::RedundantFieldNames); let single_char_binding_names_threshold = conf.single_char_binding_names_threshold; store.register_pre_expansion_pass(move || box non_expressive_names::NonExpressiveNames { diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index c59799fa1cf3..d772427889ed 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -2,14 +2,14 @@ use std::borrow::Cow; use std::ops::Range; use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_sugg, span_lint_and_then}; -use rustc_ast::ast::{Expr, ExprKind, Mac, StrLit, StrStyle}; +use rustc_ast::ast::{Expr, ExprKind, Item, ItemKind, Mac, StrLit, StrStyle}; use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_errors::Applicability; use rustc_lexer::unescape::{self, EscapeError}; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_parse::parser; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol::Symbol; use rustc_span::{BytePos, Span}; @@ -175,7 +175,12 @@ declare_clippy_lint! { "writing a literal with a format string" } -declare_lint_pass!(Write => [ +#[derive(Default)] +pub struct Write { + in_debug_impl: bool, +} + +impl_lint_pass!(Write => [ PRINT_WITH_NEWLINE, PRINTLN_EMPTY_STRING, PRINT_STDOUT, @@ -187,10 +192,34 @@ declare_lint_pass!(Write => [ ]); impl EarlyLintPass for Write { + fn check_item(&mut self, _: &EarlyContext<'_>, item: &Item) { + if let ItemKind::Impl { + of_trait: Some(trait_ref), + .. + } = &item.kind + { + let trait_name = trait_ref + .path + .segments + .iter() + .last() + .expect("path has at least one segment") + .ident + .name; + if trait_name == sym!(Debug) { + self.in_debug_impl = true; + } + } + } + + fn check_item_post(&mut self, _: &EarlyContext<'_>, _: &Item) { + self.in_debug_impl = false; + } + fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &Mac) { if mac.path == sym!(println) { span_lint(cx, PRINT_STDOUT, mac.span(), "use of `println!`"); - if let (Some(fmt_str), _) = check_tts(cx, &mac.args.inner_tokens(), false) { + if let (Some(fmt_str), _) = self.check_tts(cx, &mac.args.inner_tokens(), false) { if fmt_str.symbol == Symbol::intern("") { span_lint_and_sugg( cx, @@ -205,7 +234,7 @@ impl EarlyLintPass for Write { } } else if mac.path == sym!(print) { span_lint(cx, PRINT_STDOUT, mac.span(), "use of `print!`"); - if let (Some(fmt_str), _) = check_tts(cx, &mac.args.inner_tokens(), false) { + if let (Some(fmt_str), _) = self.check_tts(cx, &mac.args.inner_tokens(), false) { if check_newlines(&fmt_str) { span_lint_and_then( cx, @@ -226,7 +255,7 @@ impl EarlyLintPass for Write { } } } else if mac.path == sym!(write) { - if let (Some(fmt_str), _) = check_tts(cx, &mac.args.inner_tokens(), true) { + if let (Some(fmt_str), _) = self.check_tts(cx, &mac.args.inner_tokens(), true) { if check_newlines(&fmt_str) { span_lint_and_then( cx, @@ -247,7 +276,7 @@ impl EarlyLintPass for Write { } } } else if mac.path == sym!(writeln) { - if let (Some(fmt_str), expr) = check_tts(cx, &mac.args.inner_tokens(), true) { + if let (Some(fmt_str), expr) = self.check_tts(cx, &mac.args.inner_tokens(), true) { if fmt_str.symbol == Symbol::intern("") { let mut applicability = Applicability::MachineApplicable; let suggestion = expr.map_or_else( @@ -296,129 +325,136 @@ fn newline_span(fmtstr: &StrLit) -> Span { sp.with_lo(newline_sp_hi - newline_sp_len).with_hi(newline_sp_hi) } -/// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two -/// `Option`s. The first `Option` of the tuple is the macro's format string. It includes -/// the contents of the string, whether it's a raw string, and the span of the literal in the -/// source. The second `Option` in the tuple is, in the `write[ln]!` case, the expression the -/// `format_str` should be written to. -/// -/// Example: -/// -/// Calling this function on -/// ```rust -/// # use std::fmt::Write; -/// # let mut buf = String::new(); -/// # let something = "something"; -/// writeln!(buf, "string to write: {}", something); -/// ``` -/// will return -/// ```rust,ignore -/// (Some("string to write: {}"), Some(buf)) -/// ``` -#[allow(clippy::too_many_lines)] -fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (Option, Option) { - use fmt_macros::{ - AlignUnknown, ArgumentImplicitlyIs, ArgumentIs, ArgumentNamed, CountImplied, FormatSpec, Parser, Piece, - }; - let tts = tts.clone(); - - let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, None, false, false, None); - let mut expr: Option = None; - if is_write { - expr = match parser.parse_expr().map_err(|mut err| err.cancel()) { - Ok(p) => Some(p.into_inner()), - Err(_) => return (None, None), +impl Write { + /// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two + /// `Option`s. The first `Option` of the tuple is the macro's format string. It includes + /// the contents of the string, whether it's a raw string, and the span of the literal in the + /// source. The second `Option` in the tuple is, in the `write[ln]!` case, the expression the + /// `format_str` should be written to. + /// + /// Example: + /// + /// Calling this function on + /// ```rust + /// # use std::fmt::Write; + /// # let mut buf = String::new(); + /// # let something = "something"; + /// writeln!(buf, "string to write: {}", something); + /// ``` + /// will return + /// ```rust,ignore + /// (Some("string to write: {}"), Some(buf)) + /// ``` + #[allow(clippy::too_many_lines)] + fn check_tts<'a>( + &self, + cx: &EarlyContext<'a>, + tts: &TokenStream, + is_write: bool, + ) -> (Option, Option) { + use fmt_macros::{ + AlignUnknown, ArgumentImplicitlyIs, ArgumentIs, ArgumentNamed, CountImplied, FormatSpec, Parser, Piece, }; - // might be `writeln!(foo)` - if parser.expect(&token::Comma).map_err(|mut err| err.cancel()).is_err() { - return (None, expr); - } - } + let tts = tts.clone(); - let fmtstr = match parser.parse_str_lit() { - Ok(fmtstr) => fmtstr, - Err(_) => return (None, expr), - }; - let tmp = fmtstr.symbol.as_str(); - let mut args = vec![]; - let mut fmt_parser = Parser::new(&tmp, None, Vec::new(), false); - while let Some(piece) = fmt_parser.next() { - if !fmt_parser.errors.is_empty() { - return (None, expr); - } - if let Piece::NextArgument(arg) = piece { - if arg.format.ty == "?" { - // FIXME: modify rustc's fmt string parser to give us the current span - span_lint(cx, USE_DEBUG, parser.prev_token.span, "use of `Debug`-based formatting"); + let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, None, false, false, None); + let mut expr: Option = None; + if is_write { + expr = match parser.parse_expr().map_err(|mut err| err.cancel()) { + Ok(p) => Some(p.into_inner()), + Err(_) => return (None, None), + }; + // might be `writeln!(foo)` + if parser.expect(&token::Comma).map_err(|mut err| err.cancel()).is_err() { + return (None, expr); } - args.push(arg); } - } - let lint = if is_write { WRITE_LITERAL } else { PRINT_LITERAL }; - let mut idx = 0; - loop { - const SIMPLE: FormatSpec<'_> = FormatSpec { - fill: None, - align: AlignUnknown, - flags: 0, - precision: CountImplied, - precision_span: None, - width: CountImplied, - width_span: None, - ty: "", - ty_span: None, + + let fmtstr = match parser.parse_str_lit() { + Ok(fmtstr) => fmtstr, + Err(_) => return (None, expr), }; - if !parser.eat(&token::Comma) { - return (Some(fmtstr), expr); + let tmp = fmtstr.symbol.as_str(); + let mut args = vec![]; + let mut fmt_parser = Parser::new(&tmp, None, Vec::new(), false); + while let Some(piece) = fmt_parser.next() { + if !fmt_parser.errors.is_empty() { + return (None, expr); + } + if let Piece::NextArgument(arg) = piece { + if !self.in_debug_impl && arg.format.ty == "?" { + // FIXME: modify rustc's fmt string parser to give us the current span + span_lint(cx, USE_DEBUG, parser.prev_token.span, "use of `Debug`-based formatting"); + } + args.push(arg); + } } - let token_expr = if let Ok(expr) = parser.parse_expr().map_err(|mut err| err.cancel()) { - expr - } else { - return (Some(fmtstr), None); - }; - match &token_expr.kind { - ExprKind::Lit(_) => { - let mut all_simple = true; - let mut seen = false; - for arg in &args { - match arg.position { - ArgumentImplicitlyIs(n) | ArgumentIs(n) => { - if n == idx { - all_simple &= arg.format == SIMPLE; - seen = true; - } - }, - ArgumentNamed(_) => {}, + let lint = if is_write { WRITE_LITERAL } else { PRINT_LITERAL }; + let mut idx = 0; + loop { + const SIMPLE: FormatSpec<'_> = FormatSpec { + fill: None, + align: AlignUnknown, + flags: 0, + precision: CountImplied, + precision_span: None, + width: CountImplied, + width_span: None, + ty: "", + ty_span: None, + }; + if !parser.eat(&token::Comma) { + return (Some(fmtstr), expr); + } + let token_expr = if let Ok(expr) = parser.parse_expr().map_err(|mut err| err.cancel()) { + expr + } else { + return (Some(fmtstr), None); + }; + match &token_expr.kind { + ExprKind::Lit(_) => { + let mut all_simple = true; + let mut seen = false; + for arg in &args { + match arg.position { + ArgumentImplicitlyIs(n) | ArgumentIs(n) => { + if n == idx { + all_simple &= arg.format == SIMPLE; + seen = true; + } + }, + ArgumentNamed(_) => {}, + } } - } - if all_simple && seen { - span_lint(cx, lint, token_expr.span, "literal with an empty format string"); - } - idx += 1; - }, - ExprKind::Assign(lhs, rhs, _) => { - if let ExprKind::Lit(_) = rhs.kind { - if let ExprKind::Path(_, p) = &lhs.kind { - let mut all_simple = true; - let mut seen = false; - for arg in &args { - match arg.position { - ArgumentImplicitlyIs(_) | ArgumentIs(_) => {}, - ArgumentNamed(name) => { - if *p == name { - seen = true; - all_simple &= arg.format == SIMPLE; - } - }, + if all_simple && seen { + span_lint(cx, lint, token_expr.span, "literal with an empty format string"); + } + idx += 1; + }, + ExprKind::Assign(lhs, rhs, _) => { + if let ExprKind::Lit(_) = rhs.kind { + if let ExprKind::Path(_, p) = &lhs.kind { + let mut all_simple = true; + let mut seen = false; + for arg in &args { + match arg.position { + ArgumentImplicitlyIs(_) | ArgumentIs(_) => {}, + ArgumentNamed(name) => { + if *p == name { + seen = true; + all_simple &= arg.format == SIMPLE; + } + }, + } + } + if all_simple && seen { + span_lint(cx, lint, rhs.span, "literal with an empty format string"); } - } - if all_simple && seen { - span_lint(cx, lint, rhs.span, "literal with an empty format string"); } } - } - }, - _ => idx += 1, + }, + _ => idx += 1, + } } } } From a540b5ca2e4128857ac271f1aea26fe3023764ee Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 14 Jan 2020 16:28:20 +0100 Subject: [PATCH 161/243] Update stderr --- tests/ui/print.stderr | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tests/ui/print.stderr b/tests/ui/print.stderr index 12c5a0bdaa02..208d95326285 100644 --- a/tests/ui/print.stderr +++ b/tests/ui/print.stderr @@ -6,12 +6,6 @@ LL | write!(f, "{:?}", 43.1415) | = note: `-D clippy::use-debug` implied by `-D warnings` -error: use of `Debug`-based formatting - --> $DIR/print.rs:18:19 - | -LL | write!(f, "{:?}", 42.718) - | ^^^^^^ - error: use of `println!` --> $DIR/print.rs:23:5 | @@ -56,5 +50,5 @@ error: use of `Debug`-based formatting LL | print!("Hello {:#?}", "#orld"); | ^^^^^^^^^^^^^ -error: aborting due to 9 previous errors +error: aborting due to 8 previous errors From 58cea334ec1ef959e8ae54627feb1850b051faac Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 3 Mar 2020 10:52:56 +0100 Subject: [PATCH 162/243] Use lang items instead of get_trait_def_id where possible --- clippy_lints/src/doc.rs | 4 ++-- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 2 +- clippy_lints/src/utils/paths.rs | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 89a68990c87e..35578ae68a46 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -1,4 +1,4 @@ -use crate::utils::{get_trait_def_id, implements_trait, is_entrypoint_fn, match_type, paths, return_ty, span_lint}; +use crate::utils::{implements_trait, is_entrypoint_fn, match_type, paths, return_ty, span_lint}; use if_chain::if_chain; use itertools::Itertools; use rustc::lint::in_external_macro; @@ -227,7 +227,7 @@ fn lint_for_missing_headers<'a, 'tcx>( } else { if_chain! { if let Some(body_id) = body_id; - if let Some(future) = get_trait_def_id(cx, &paths::FUTURE); + if let Some(future) = cx.tcx.lang_items().future_trait(); let def_id = cx.tcx.hir().body_owner_def_id(body_id); let mir = cx.tcx.optimized_mir(def_id); let ret_ty = mir.return_ty(); diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 65643d89df57..2c4c29913cff 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -67,7 +67,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd { }; let implements_partial_ord = { - if let Some(id) = utils::get_trait_def_id(cx, &paths::PARTIAL_ORD) { + if let Some(id) = cx.tcx.lang_items().partial_ord_trait() { utils::implements_trait(cx, ty, id, &[]) } else { return; diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 96337e42b544..cffdb218cde2 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -36,7 +36,6 @@ pub const FMT_ARGUMENTS_NEW_V1_FORMATTED: [&str; 4] = ["core", "fmt", "Arguments pub const FMT_ARGUMENTV1_NEW: [&str; 4] = ["core", "fmt", "ArgumentV1", "new"]; pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"]; pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"]; -pub const FUTURE: [&str; 3] = ["std", "future", "Future"]; pub const HASH: [&str; 2] = ["hash", "Hash"]; pub const HASHMAP: [&str; 5] = ["std", "collections", "hash", "map", "HashMap"]; pub const HASHMAP_ENTRY: [&str; 5] = ["std", "collections", "hash", "map", "Entry"]; @@ -69,7 +68,6 @@ pub const ORD: [&str; 3] = ["core", "cmp", "Ord"]; pub const OS_STRING: [&str; 4] = ["std", "ffi", "os_str", "OsString"]; pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"]; pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"]; -pub const PARTIAL_ORD: [&str; 3] = ["core", "cmp", "PartialOrd"]; pub const PATH: [&str; 3] = ["std", "path", "Path"]; pub const PATH_BUF: [&str; 3] = ["std", "path", "PathBuf"]; pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"]; From 91042db2e8976174d3e568f7ce780a15322847f6 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 3 Mar 2020 10:53:14 +0100 Subject: [PATCH 163/243] Add path for display trait --- clippy_lints/src/inherent_to_string.rs | 3 +-- clippy_lints/src/utils/paths.rs | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/inherent_to_string.rs b/clippy_lints/src/inherent_to_string.rs index 10fe8f28eaba..24c0b1cb80e6 100644 --- a/clippy_lints/src/inherent_to_string.rs +++ b/clippy_lints/src/inherent_to_string.rs @@ -120,8 +120,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InherentToString { } fn show_lint(cx: &LateContext<'_, '_>, item: &ImplItem<'_>) { - let display_trait_id = - get_trait_def_id(cx, &["core", "fmt", "Display"]).expect("Failed to get trait ID of `Display`!"); + let display_trait_id = get_trait_def_id(cx, &paths::DISPLAY_TRAIT).expect("Failed to get trait ID of `Display`!"); // Get the real type of 'self' let fn_def_id = cx.tcx.hir().local_def_id(item.hir_id); diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index cffdb218cde2..5ec04d965c86 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -24,6 +24,7 @@ pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "defa pub const DEREF_MUT_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "DerefMut", "deref_mut"]; pub const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"]; pub const DISPLAY_FMT_METHOD: [&str; 4] = ["core", "fmt", "Display", "fmt"]; +pub const DISPLAY_TRAIT: [&str; 3] = ["core", "fmt", "Display"]; pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"]; pub const DROP: [&str; 3] = ["core", "mem", "drop"]; pub const DROP_TRAIT: [&str; 4] = ["core", "ops", "drop", "Drop"]; From 3d44ad2e320929baa039f10a98ffb46e6bcb3acc Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 3 Mar 2020 05:53:41 +0900 Subject: [PATCH 164/243] Use `try_eval_usize` over `eval_usize` --- clippy_lints/src/consts.rs | 8 +++++++- clippy_lints/src/indexing_slicing.rs | 6 +++++- clippy_lints/src/methods/mod.rs | 8 +++++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 9bb7b540d68f..ceda5d1a7c37 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -231,7 +231,13 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { ExprKind::Tup(ref tup) => self.multi(tup).map(Constant::Tuple), ExprKind::Repeat(ref value, _) => { let n = match self.tables.expr_ty(e).kind { - ty::Array(_, n) => n.eval_usize(self.lcx.tcx, self.lcx.param_env), + ty::Array(_, n) => { + if let Some(n) = n.try_eval_usize(self.lcx.tcx, self.lcx.param_env) { + n + } else { + return None; + } + }, _ => span_bug!(e.span, "typeck error"), }; self.expr(value).map(|v| Constant::Repeat(Box::new(v), n)) diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 21444ffb23d7..65d2dd581068 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -92,7 +92,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { if let Some(range) = higher::range(cx, index) { // Ranged indexes, i.e., &x[n..m], &x[n..], &x[..n] and &x[..] if let ty::Array(_, s) = ty.kind { - let size: u128 = s.eval_usize(cx.tcx, cx.param_env).into(); + let size: u128 = if let Some(size) = s.try_eval_usize(cx.tcx, cx.param_env) { + size.into() + } else { + return; + }; let const_range = to_const_range(cx, range, size); diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 06fb9516456e..eef510540901 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2324,7 +2324,13 @@ fn derefs_to_slice<'a, 'tcx>( ty::Slice(_) => true, ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), ty::Adt(..) => is_type_diagnostic_item(cx, ty, Symbol::intern("vec_type")), - ty::Array(_, size) => size.eval_usize(cx.tcx, cx.param_env) < 32, + ty::Array(_, size) => { + if let Some(size) = size.try_eval_usize(cx.tcx, cx.param_env) { + size < 32 + } else { + false + } + }, ty::Ref(_, inner, _) => may_slice(cx, inner), _ => false, } From 46ee6b1840b3ab3c06c9f8ba3bb097f25b5c174a Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 3 Mar 2020 21:39:45 +0900 Subject: [PATCH 165/243] Add regression test --- tests/ui/crashes/ice-5223.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tests/ui/crashes/ice-5223.rs diff --git a/tests/ui/crashes/ice-5223.rs b/tests/ui/crashes/ice-5223.rs new file mode 100644 index 000000000000..9bb2e227fc12 --- /dev/null +++ b/tests/ui/crashes/ice-5223.rs @@ -0,0 +1,18 @@ +// Regression test for #5233 + +#![feature(const_generics)] +#![allow(incomplete_features)] +#![warn(clippy::indexing_slicing, clippy::iter_cloned_collect)] + +pub struct KotomineArray { + arr: [T; N], +} + +impl KotomineArray { + pub fn ice(self) { + let _ = self.arr[..]; + let _ = self.arr.iter().cloned().collect::>(); + } +} + +fn main() {} From 94867fbbb8bb0562ee0d6263668610fb858429dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Tue, 3 Mar 2020 15:13:25 +0100 Subject: [PATCH 166/243] use question mark operator --- clippy_lints/src/consts.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index ceda5d1a7c37..ec8ba70bf741 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -231,13 +231,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { ExprKind::Tup(ref tup) => self.multi(tup).map(Constant::Tuple), ExprKind::Repeat(ref value, _) => { let n = match self.tables.expr_ty(e).kind { - ty::Array(_, n) => { - if let Some(n) = n.try_eval_usize(self.lcx.tcx, self.lcx.param_env) { - n - } else { - return None; - } - }, + ty::Array(_, n) => n.try_eval_usize(self.lcx.tcx, self.lcx.param_env)?, _ => span_bug!(e.span, "typeck error"), }; self.expr(value).map(|v| Constant::Repeat(Box::new(v), n)) From e633ea823c5bf9e66c489b42f8eb510ff857abf8 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 4 Mar 2020 04:32:42 +0900 Subject: [PATCH 167/243] Revive rls integration test --- .github/workflows/clippy_bors.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index ec192de191b1..a4f7b64cb6a7 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -231,8 +231,7 @@ jobs: matrix: integration: - 'rust-lang/cargo' - # FIXME: Re-enable once we can test with rls again. - # - 'rust-lang/rls' + - 'rust-lang/rls' - 'rust-lang/chalk' - 'rust-lang/rustfmt' - 'Marwes/combine' From f8e949fa1cc9af57f88babe74ea65e51730e7a86 Mon Sep 17 00:00:00 2001 From: JarredAllen Date: Tue, 3 Mar 2020 15:52:53 -0800 Subject: [PATCH 168/243] Recommended changes from flip1995 --- clippy_lints/src/floating_point_arithmetic.rs | 113 ++++++++---------- tests/ui/floating_point_abs.fixed | 98 +++++++++++++++ tests/ui/floating_point_abs.rs | 17 ++- tests/ui/floating_point_abs.stderr | 32 ++--- 4 files changed, 179 insertions(+), 81 deletions(-) create mode 100644 tests/ui/floating_point_abs.fixed diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index de2c245f451d..6a58b27f0651 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -1,17 +1,17 @@ use crate::consts::{ - constant, Constant, + constant, constant_simple, Constant, Constant::{F32, F64}, }; use crate::utils::{higher, span_lint_and_sugg, sugg, SpanlessEq}; use if_chain::if_chain; use rustc::ty; use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Lit, UnOp}; +use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; -use rustc_ast::ast::{self, FloatTy, LitFloatType, LitKind}; +use rustc_ast::ast; use std::f32::consts as f32_consts; use std::f64::consts as f64_consts; use sugg::{format_numeric_literal, Sugg}; @@ -378,8 +378,8 @@ fn check_mul_add(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { fn is_testing_positive(cx: &LateContext<'_, '_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool { if let ExprKind::Binary(Spanned { node: op, .. }, left, right) = expr.kind { match op { - BinOpKind::Gt | BinOpKind::Ge => is_zero(right) && are_exprs_equal(cx, left, test), - BinOpKind::Lt | BinOpKind::Le => is_zero(left) && are_exprs_equal(cx, right, test), + BinOpKind::Gt | BinOpKind::Ge => is_zero(cx, right) && are_exprs_equal(cx, left, test), + BinOpKind::Lt | BinOpKind::Le => is_zero(cx, left) && are_exprs_equal(cx, right, test), _ => false, } } else { @@ -387,11 +387,12 @@ fn is_testing_positive(cx: &LateContext<'_, '_>, expr: &Expr<'_>, test: &Expr<'_ } } +/// See [`is_testing_positive`] fn is_testing_negative(cx: &LateContext<'_, '_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool { if let ExprKind::Binary(Spanned { node: op, .. }, left, right) = expr.kind { match op { - BinOpKind::Gt | BinOpKind::Ge => is_zero(left) && are_exprs_equal(cx, right, test), - BinOpKind::Lt | BinOpKind::Le => is_zero(right) && are_exprs_equal(cx, left, test), + BinOpKind::Gt | BinOpKind::Ge => is_zero(cx, left) && are_exprs_equal(cx, right, test), + BinOpKind::Lt | BinOpKind::Le => is_zero(cx, right) && are_exprs_equal(cx, left, test), _ => false, } } else { @@ -404,85 +405,69 @@ fn are_exprs_equal(cx: &LateContext<'_, '_>, expr1: &Expr<'_>, expr2: &Expr<'_>) } /// Returns true iff expr is some zero literal -fn is_zero(expr: &Expr<'_>) -> bool { - if let ExprKind::Lit(Lit { node: lit, .. }) = &expr.kind { - match lit { - LitKind::Int(0, _) => true, - LitKind::Float(symb, LitFloatType::Unsuffixed) - | LitKind::Float(symb, LitFloatType::Suffixed(FloatTy::F64)) => { - symb.as_str().parse::().unwrap() == 0.0 - }, - LitKind::Float(symb, LitFloatType::Suffixed(FloatTy::F32)) => symb.as_str().parse::().unwrap() == 0.0, - _ => false, - } - } else { - false +fn is_zero(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + match constant_simple(cx, cx.tables, expr) { + Some(Constant::Int(i)) => i == 0, + Some(Constant::F32(f)) => f == 0.0, + Some(Constant::F64(f)) => f == 0.0, + _ => false, } } -/// If the expressions are not opposites, return None -/// Otherwise, return true if expr2 = -expr1, false if expr1 = -expr2 and return the positive -/// expression -fn are_opposites<'a>( +/// If the two expressions are negations of each other, then it returns +/// a tuple, in which the first element is true iff expr1 is the +/// positive expressions, and the second element is the positive +/// one of the two expressions +/// If the two expressions are not negations of each other, then it +/// returns None. +fn are_negated<'a>( cx: &LateContext<'_, '_>, expr1: &'a Expr<'a>, expr2: &'a Expr<'a>, ) -> Option<(bool, &'a Expr<'a>)> { - if let ExprKind::Block( - Block { - stmts: [], - expr: Some(expr1_inner), - .. - }, - _, - ) = &expr1.kind - { - if let ExprKind::Block( - Block { - stmts: [], - expr: Some(expr2_inner), - .. - }, - _, - ) = &expr2.kind - { - if let ExprKind::Unary(UnOp::UnNeg, expr1_neg) = &expr1_inner.kind { - if are_exprs_equal(cx, expr1_neg, expr2_inner) { - return Some((false, expr2_inner)); - } - } - if let ExprKind::Unary(UnOp::UnNeg, expr2_neg) = &expr2_inner.kind { - if are_exprs_equal(cx, expr1_inner, expr2_neg) { - return Some((true, expr1_inner)); - } - } + if let ExprKind::Unary(UnOp::UnNeg, expr1_negated) = &expr1.kind { + if are_exprs_equal(cx, expr1_negated, expr2) { + return Some((false, expr2)); + } + } + if let ExprKind::Unary(UnOp::UnNeg, expr2_negated) = &expr2.kind { + if are_exprs_equal(cx, expr1, expr2_negated) { + return Some((true, expr1)); } } None } fn check_custom_abs(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { - if let Some((cond, body, Some(else_body))) = higher::if_block(&expr) { - if let Some((expr1_pos, body)) = are_opposites(cx, body, else_body) { - let pos_abs_sugg = ( - "This looks like you've implemented your own absolute value function", + if_chain! { + if let Some((cond, body, Some(else_body))) = higher::if_block(&expr); + if let ExprKind::Block(block, _) = body.kind; + if block.stmts.is_empty(); + if let Some(if_body_expr) = block.expr; + if let ExprKind::Block(else_block, _) = else_body.kind; + if else_block.stmts.is_empty(); + if let Some(else_body_expr) = else_block.expr; + if let Some((if_expr_positive, body)) = are_negated(cx, if_body_expr, else_body_expr); + then { + let positive_abs_sugg = ( + "manual implementation of `abs` method", format!("{}.abs()", Sugg::hir(cx, body, "..")), ); - let neg_abs_sugg = ( - "This looks like you've implemented your own negative absolute value function", + let negative_abs_sugg = ( + "manual implementation of negation of `abs` method", format!("-{}.abs()", Sugg::hir(cx, body, "..")), ); let sugg = if is_testing_positive(cx, cond, body) { - if expr1_pos { - pos_abs_sugg + if if_expr_positive { + positive_abs_sugg } else { - neg_abs_sugg + negative_abs_sugg } } else if is_testing_negative(cx, cond, body) { - if expr1_pos { - neg_abs_sugg + if if_expr_positive { + negative_abs_sugg } else { - pos_abs_sugg + positive_abs_sugg } } else { return; diff --git a/tests/ui/floating_point_abs.fixed b/tests/ui/floating_point_abs.fixed new file mode 100644 index 000000000000..39cec0727a19 --- /dev/null +++ b/tests/ui/floating_point_abs.fixed @@ -0,0 +1,98 @@ +// run-rustfix +#![warn(clippy::suboptimal_flops)] + +struct A { + a: f64, + b: f64, +} + +fn fake_abs1(num: f64) -> f64 { + num.abs() +} + +fn fake_abs2(num: f64) -> f64 { + num.abs() +} + +fn fake_abs3(a: A) -> f64 { + a.a.abs() +} + +fn fake_abs4(num: f64) -> f64 { + num.abs() +} + +fn fake_abs5(a: A) -> f64 { + a.a.abs() +} + +fn fake_nabs1(num: f64) -> f64 { + -num.abs() +} + +fn fake_nabs2(num: f64) -> f64 { + -num.abs() +} + +fn fake_nabs3(a: A) -> A { + A { + a: -a.a.abs(), + b: a.b, + } +} + +fn not_fake_abs1(num: f64) -> f64 { + if num > 0.0 { + num + } else { + -num - 1f64 + } +} + +fn not_fake_abs2(num: f64) -> f64 { + if num > 0.0 { + num + 1.0 + } else { + -(num + 1.0) + } +} + +fn not_fake_abs3(num1: f64, num2: f64) -> f64 { + if num1 > 0.0 { + num2 + } else { + -num2 + } +} + +fn not_fake_abs4(a: A) -> f64 { + if a.a > 0.0 { + a.b + } else { + -a.b + } +} + +fn not_fake_abs5(a: A) -> f64 { + if a.a > 0.0 { + a.a + } else { + -a.b + } +} + +fn main() { + fake_abs1(5.0); + fake_abs2(5.0); + fake_abs3(A { a: 5.0, b: 5.0 } ); + fake_abs4(5.0); + fake_abs5(A { a: 5.0, b: 5.0 } ); + fake_nabs1(5.0); + fake_nabs2(5.0); + fake_nabs3(A { a: 5.0, b: 5.0 } ); + not_fake_abs1(5.0); + not_fake_abs2(5.0); + not_fake_abs3(5.0, 5.0); + not_fake_abs4(A { a: 5.0, b: 5.0 } ); + not_fake_abs5(A { a: 5.0, b: 5.0 } ); +} diff --git a/tests/ui/floating_point_abs.rs b/tests/ui/floating_point_abs.rs index b0c15e57e40f..780eb3547158 100644 --- a/tests/ui/floating_point_abs.rs +++ b/tests/ui/floating_point_abs.rs @@ -1,3 +1,4 @@ +// run-rustfix #![warn(clippy::suboptimal_flops)] struct A { @@ -108,4 +109,18 @@ fn not_fake_abs5(a: A) -> f64 { } } -fn main() {} +fn main() { + fake_abs1(5.0); + fake_abs2(5.0); + fake_abs3(A { a: 5.0, b: 5.0 } ); + fake_abs4(5.0); + fake_abs5(A { a: 5.0, b: 5.0 } ); + fake_nabs1(5.0); + fake_nabs2(5.0); + fake_nabs3(A { a: 5.0, b: 5.0 } ); + not_fake_abs1(5.0); + not_fake_abs2(5.0); + not_fake_abs3(5.0, 5.0); + not_fake_abs4(A { a: 5.0, b: 5.0 } ); + not_fake_abs5(A { a: 5.0, b: 5.0 } ); +} diff --git a/tests/ui/floating_point_abs.stderr b/tests/ui/floating_point_abs.stderr index 44a9dbee5bbd..74a71f2ca7c5 100644 --- a/tests/ui/floating_point_abs.stderr +++ b/tests/ui/floating_point_abs.stderr @@ -1,5 +1,5 @@ -error: This looks like you've implemented your own absolute value function - --> $DIR/floating_point_abs.rs:9:5 +error: manual implementation of `abs` method + --> $DIR/floating_point_abs.rs:10:5 | LL | / if num >= 0.0 { LL | | num @@ -10,8 +10,8 @@ LL | | } | = note: `-D clippy::suboptimal-flops` implied by `-D warnings` -error: This looks like you've implemented your own absolute value function - --> $DIR/floating_point_abs.rs:17:5 +error: manual implementation of `abs` method + --> $DIR/floating_point_abs.rs:18:5 | LL | / if 0.0 < num { LL | | num @@ -20,8 +20,8 @@ LL | | -num LL | | } | |_____^ help: try: `num.abs()` -error: This looks like you've implemented your own absolute value function - --> $DIR/floating_point_abs.rs:25:5 +error: manual implementation of `abs` method + --> $DIR/floating_point_abs.rs:26:5 | LL | / if a.a > 0.0 { LL | | a.a @@ -30,8 +30,8 @@ LL | | -a.a LL | | } | |_____^ help: try: `a.a.abs()` -error: This looks like you've implemented your own absolute value function - --> $DIR/floating_point_abs.rs:33:5 +error: manual implementation of `abs` method + --> $DIR/floating_point_abs.rs:34:5 | LL | / if 0.0 >= num { LL | | -num @@ -40,8 +40,8 @@ LL | | num LL | | } | |_____^ help: try: `num.abs()` -error: This looks like you've implemented your own absolute value function - --> $DIR/floating_point_abs.rs:41:5 +error: manual implementation of `abs` method + --> $DIR/floating_point_abs.rs:42:5 | LL | / if a.a < 0.0 { LL | | -a.a @@ -50,8 +50,8 @@ LL | | a.a LL | | } | |_____^ help: try: `a.a.abs()` -error: This looks like you've implemented your own negative absolute value function - --> $DIR/floating_point_abs.rs:49:5 +error: manual implementation of negation of `abs` method + --> $DIR/floating_point_abs.rs:50:5 | LL | / if num < 0.0 { LL | | num @@ -60,8 +60,8 @@ LL | | -num LL | | } | |_____^ help: try: `-num.abs()` -error: This looks like you've implemented your own negative absolute value function - --> $DIR/floating_point_abs.rs:57:5 +error: manual implementation of negation of `abs` method + --> $DIR/floating_point_abs.rs:58:5 | LL | / if 0.0 >= num { LL | | num @@ -70,8 +70,8 @@ LL | | -num LL | | } | |_____^ help: try: `-num.abs()` -error: This looks like you've implemented your own negative absolute value function - --> $DIR/floating_point_abs.rs:66:12 +error: manual implementation of negation of `abs` method + --> $DIR/floating_point_abs.rs:67:12 | LL | a: if a.a >= 0.0 { -a.a } else { a.a }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-a.a.abs()` From a640696cdf7f14b599ea1bca1c9cbbe1cf1b1fdf Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 4 Mar 2020 00:54:27 +0100 Subject: [PATCH 169/243] Rustup to rust-lang/rust#69506 --- tests/ui/author/blocks.rs | 2 +- tests/ui/author/blocks.stdout | 5 +---- tests/ui/swap.fixed | 2 +- tests/ui/swap.rs | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/ui/author/blocks.rs b/tests/ui/author/blocks.rs index 6034762d130a..a8068436b70b 100644 --- a/tests/ui/author/blocks.rs +++ b/tests/ui/author/blocks.rs @@ -1,5 +1,5 @@ #![feature(stmt_expr_attributes)] -#![allow(redundant_semicolon, clippy::no_effect)] +#![allow(redundant_semicolons, clippy::no_effect)] #[rustfmt::skip] fn main() { diff --git a/tests/ui/author/blocks.stdout b/tests/ui/author/blocks.stdout index c7127db904a3..c8ef75e48fc2 100644 --- a/tests/ui/author/blocks.stdout +++ b/tests/ui/author/blocks.stdout @@ -1,10 +1,7 @@ if_chain! { if let ExprKind::Block(ref block) = expr.kind; if let Some(trailing_expr) = &block.expr; - if block.stmts.len() == 1; - if let StmtKind::Semi(ref e, _) = block.stmts[0].kind - if let ExprKind::Tup(ref elements) = e.kind; - if elements.len() == 0; + if block.stmts.len() == 0; then { // report your lint here } diff --git a/tests/ui/swap.fixed b/tests/ui/swap.fixed index 82931bf91fdf..0f8f839a0d54 100644 --- a/tests/ui/swap.fixed +++ b/tests/ui/swap.fixed @@ -5,7 +5,7 @@ clippy::blacklisted_name, clippy::no_effect, clippy::redundant_clone, - redundant_semicolon, + redundant_semicolons, unused_assignments )] diff --git a/tests/ui/swap.rs b/tests/ui/swap.rs index 4582db4b40e2..5763d9e82d48 100644 --- a/tests/ui/swap.rs +++ b/tests/ui/swap.rs @@ -5,7 +5,7 @@ clippy::blacklisted_name, clippy::no_effect, clippy::redundant_clone, - redundant_semicolon, + redundant_semicolons, unused_assignments )] From fe342f32912b3e5a6b48e9e99615319d8c13bd2b Mon Sep 17 00:00:00 2001 From: JarredAllen Date: Tue, 3 Mar 2020 18:06:59 -0800 Subject: [PATCH 170/243] Ran cargo dev fmt --- clippy_lints/src/floating_point_arithmetic.rs | 6 +----- tests/ui/floating_point_abs.rs | 10 +++++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 6a58b27f0651..0fcfb7b88497 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -420,11 +420,7 @@ fn is_zero(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { /// one of the two expressions /// If the two expressions are not negations of each other, then it /// returns None. -fn are_negated<'a>( - cx: &LateContext<'_, '_>, - expr1: &'a Expr<'a>, - expr2: &'a Expr<'a>, -) -> Option<(bool, &'a Expr<'a>)> { +fn are_negated<'a>(cx: &LateContext<'_, '_>, expr1: &'a Expr<'a>, expr2: &'a Expr<'a>) -> Option<(bool, &'a Expr<'a>)> { if let ExprKind::Unary(UnOp::UnNeg, expr1_negated) = &expr1.kind { if are_exprs_equal(cx, expr1_negated, expr2) { return Some((false, expr2)); diff --git a/tests/ui/floating_point_abs.rs b/tests/ui/floating_point_abs.rs index 780eb3547158..cbf9c94e41e6 100644 --- a/tests/ui/floating_point_abs.rs +++ b/tests/ui/floating_point_abs.rs @@ -112,15 +112,15 @@ fn not_fake_abs5(a: A) -> f64 { fn main() { fake_abs1(5.0); fake_abs2(5.0); - fake_abs3(A { a: 5.0, b: 5.0 } ); + fake_abs3(A { a: 5.0, b: 5.0 }); fake_abs4(5.0); - fake_abs5(A { a: 5.0, b: 5.0 } ); + fake_abs5(A { a: 5.0, b: 5.0 }); fake_nabs1(5.0); fake_nabs2(5.0); - fake_nabs3(A { a: 5.0, b: 5.0 } ); + fake_nabs3(A { a: 5.0, b: 5.0 }); not_fake_abs1(5.0); not_fake_abs2(5.0); not_fake_abs3(5.0, 5.0); - not_fake_abs4(A { a: 5.0, b: 5.0 } ); - not_fake_abs5(A { a: 5.0, b: 5.0 } ); + not_fake_abs4(A { a: 5.0, b: 5.0 }); + not_fake_abs5(A { a: 5.0, b: 5.0 }); } From c3e96d14ab1b90b7e4ff1ea2222419a22c011ed5 Mon Sep 17 00:00:00 2001 From: JarredAllen Date: Tue, 3 Mar 2020 19:23:04 -0800 Subject: [PATCH 171/243] Update test case answers to match cargo dev fmt --- tests/ui/floating_point_abs.fixed | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/ui/floating_point_abs.fixed b/tests/ui/floating_point_abs.fixed index 39cec0727a19..b623e4988e7d 100644 --- a/tests/ui/floating_point_abs.fixed +++ b/tests/ui/floating_point_abs.fixed @@ -84,15 +84,15 @@ fn not_fake_abs5(a: A) -> f64 { fn main() { fake_abs1(5.0); fake_abs2(5.0); - fake_abs3(A { a: 5.0, b: 5.0 } ); + fake_abs3(A { a: 5.0, b: 5.0 }); fake_abs4(5.0); - fake_abs5(A { a: 5.0, b: 5.0 } ); + fake_abs5(A { a: 5.0, b: 5.0 }); fake_nabs1(5.0); fake_nabs2(5.0); - fake_nabs3(A { a: 5.0, b: 5.0 } ); + fake_nabs3(A { a: 5.0, b: 5.0 }); not_fake_abs1(5.0); not_fake_abs2(5.0); not_fake_abs3(5.0, 5.0); - not_fake_abs4(A { a: 5.0, b: 5.0 } ); - not_fake_abs5(A { a: 5.0, b: 5.0 } ); + not_fake_abs4(A { a: 5.0, b: 5.0 }); + not_fake_abs5(A { a: 5.0, b: 5.0 }); } From 2aa14c9beb48ad780412df747b0a64b90eb5f13e Mon Sep 17 00:00:00 2001 From: ThibsG Date: Sun, 1 Mar 2020 17:36:14 +0100 Subject: [PATCH 172/243] Add restrictive pat use in full binded struct --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 2 + clippy_lints/src/matches.rs | 59 ++++++++++++++++++- src/lintlist/mod.rs | 9 ++- tests/ui/rest_pat_in_fully_bound_structs.rs | 30 ++++++++++ .../ui/rest_pat_in_fully_bound_structs.stderr | 27 +++++++++ 7 files changed, 125 insertions(+), 5 deletions(-) create mode 100644 tests/ui/rest_pat_in_fully_bound_structs.rs create mode 100644 tests/ui/rest_pat_in_fully_bound_structs.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 99e84ea51931..4d8e24943897 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1321,6 +1321,7 @@ Released 2018-09-13 [`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref [`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro [`replace_consts`]: https://rust-lang.github.io/rust-clippy/master/index.html#replace_consts +[`rest_pat_in_fully_bound_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#rest_pat_in_fully_bound_structs [`result_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_expect_used [`result_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unit_fn [`result_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else diff --git a/README.md b/README.md index 1300c5ad47bf..6915b1bde025 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 358 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 359 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 4157d33079ca..327cc56cafa5 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -610,6 +610,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &matches::MATCH_REF_PATS, &matches::MATCH_SINGLE_BINDING, &matches::MATCH_WILD_ERR_ARM, + &matches::REST_PAT_IN_FULLY_BOUND_STRUCTS, &matches::SINGLE_MATCH, &matches::SINGLE_MATCH_ELSE, &matches::WILDCARD_ENUM_MATCH_ARM, @@ -1026,6 +1027,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&integer_division::INTEGER_DIVISION), LintId::of(&let_underscore::LET_UNDERSCORE_MUST_USE), LintId::of(&literal_representation::DECIMAL_LITERAL_REPRESENTATION), + LintId::of(&matches::REST_PAT_IN_FULLY_BOUND_STRUCTS), LintId::of(&matches::WILDCARD_ENUM_MATCH_ARM), LintId::of(&mem_forget::MEM_FORGET), LintId::of(&methods::CLONE_ON_REF_PTR), diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 6f1efe0fd85c..9668c5d83499 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -14,8 +14,8 @@ use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::def::CtorKind; use rustc_hir::{ - print, Arm, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, Local, MatchSource, Mutability, PatKind, QPath, - RangeEnd, + print, Arm, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, Local, MatchSource, Mutability, Pat, PatKind, + QPath, RangeEnd, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -311,6 +311,36 @@ declare_clippy_lint! { "a match with a single binding instead of using `let` statement" } +declare_clippy_lint! { + /// **What it does:** Checks for unnecessary '..' pattern binding on struct when all fields are explicitly matched. + /// + /// **Why is this bad?** Correctness and readability. It's like having a wildcard pattern after + /// matching all enum variants explicitly. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust + /// # struct A { a: i32 } + /// let a = A { a: 5 }; + /// + /// // Bad + /// match a { + /// A { a: 5, .. } => {}, + /// _ => {}, + /// } + /// + /// // Good + /// match a { + /// A { a: 5 } => {}, + /// _ => {}, + /// } + /// ``` + pub REST_PAT_IN_FULLY_BOUND_STRUCTS, + restriction, + "a match on a struct that binds all fields but still uses the wildcard pattern" +} + #[derive(Default)] pub struct Matches { infallible_destructuring_match_linted: bool, @@ -327,7 +357,8 @@ impl_lint_pass!(Matches => [ WILDCARD_ENUM_MATCH_ARM, WILDCARD_IN_OR_PATTERNS, MATCH_SINGLE_BINDING, - INFALLIBLE_DESTRUCTURING_MATCH + INFALLIBLE_DESTRUCTURING_MATCH, + REST_PAT_IN_FULLY_BOUND_STRUCTS ]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Matches { @@ -388,6 +419,28 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Matches { } } } + + fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat<'_>) { + if_chain! { + if let PatKind::Struct(ref qpath, fields, true) = pat.kind; + if let QPath::Resolved(_, ref path) = qpath; + if let Some(def_id) = path.res.opt_def_id(); + let ty = cx.tcx.type_of(def_id); + if let ty::Adt(def, _) = ty.kind; + if def.is_struct() || def.is_union(); + if fields.len() == def.non_enum_variant().fields.len(); + + then { + span_lint_and_help( + cx, + REST_PAT_IN_FULLY_BOUND_STRUCTS, + pat.span, + "unnecessary use of `..` pattern in struct binding. All fields were already bound", + "consider removing `..` from this binding", + ); + } + } + } } #[rustfmt::skip] diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 15e6a4b6036a..2b93e4279f0d 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -6,7 +6,7 @@ pub use lint::Lint; pub use lint::LINT_LEVELS; // begin lint list, do not remove this comment, it’s used in `update_lints` -pub const ALL_LINTS: [Lint; 358] = [ +pub const ALL_LINTS: [Lint; 359] = [ Lint { name: "absurd_extreme_comparisons", group: "correctness", @@ -1785,6 +1785,13 @@ pub const ALL_LINTS: [Lint; 358] = [ deprecation: None, module: "replace_consts", }, + Lint { + name: "rest_pat_in_fully_bound_structs", + group: "restriction", + desc: "a match on a struct that binds all fields but still uses the wildcard pattern", + deprecation: None, + module: "matches", + }, Lint { name: "result_expect_used", group: "restriction", diff --git a/tests/ui/rest_pat_in_fully_bound_structs.rs b/tests/ui/rest_pat_in_fully_bound_structs.rs new file mode 100644 index 000000000000..22e4d4edd783 --- /dev/null +++ b/tests/ui/rest_pat_in_fully_bound_structs.rs @@ -0,0 +1,30 @@ +#![warn(clippy::rest_pat_in_fully_bound_structs)] + +struct A { + a: i32, + b: i64, + c: &'static str, +} + +fn main() { + let a_struct = A { a: 5, b: 42, c: "A" }; + + match a_struct { + A { a: 5, b: 42, c: "", .. } => {}, // Lint + A { a: 0, b: 0, c: "", .. } => {}, // Lint + _ => {}, + } + + match a_struct { + A { a: 5, b: 42, .. } => {}, + A { a: 0, b: 0, c: "", .. } => {}, // Lint + _ => {}, + } + + // No lint + match a_struct { + A { a: 5, .. } => {}, + A { a: 0, b: 0, .. } => {}, + _ => {}, + } +} diff --git a/tests/ui/rest_pat_in_fully_bound_structs.stderr b/tests/ui/rest_pat_in_fully_bound_structs.stderr new file mode 100644 index 000000000000..effa46b4b0fa --- /dev/null +++ b/tests/ui/rest_pat_in_fully_bound_structs.stderr @@ -0,0 +1,27 @@ +error: unnecessary use of `..` pattern in struct binding. All fields were already bound + --> $DIR/rest_pat_in_fully_bound_structs.rs:13:9 + | +LL | A { a: 5, b: 42, c: "", .. } => {}, // Lint + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::rest-pat-in-fully-bound-structs` implied by `-D warnings` + = help: consider removing `..` from this binding + +error: unnecessary use of `..` pattern in struct binding. All fields were already bound + --> $DIR/rest_pat_in_fully_bound_structs.rs:14:9 + | +LL | A { a: 0, b: 0, c: "", .. } => {}, // Lint + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider removing `..` from this binding + +error: unnecessary use of `..` pattern in struct binding. All fields were already bound + --> $DIR/rest_pat_in_fully_bound_structs.rs:20:9 + | +LL | A { a: 0, b: 0, c: "", .. } => {}, // Lint + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider removing `..` from this binding + +error: aborting due to 3 previous errors + From 45f61ead2cf693a42025778b2315259bd95495e4 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Wed, 4 Mar 2020 16:59:16 +0900 Subject: [PATCH 173/243] Lint `if let Some` in question_mark lint --- clippy_lints/src/question_mark.rs | 55 +++++++++++++++++++++++++++++-- clippy_lints/src/types.rs | 7 +--- tests/ui/question_mark.rs | 26 +++++++++++++++ tests/ui/question_mark.stderr | 55 ++++++++++++++++++++++++------- 4 files changed, 123 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index f21c2985d194..5ad580aa052b 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -1,13 +1,15 @@ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{def, Block, Expr, ExprKind, StmtKind}; +use rustc_hir::{def, BindingAnnotation, Block, Expr, ExprKind, MatchSource, PatKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use crate::utils::paths::{OPTION, OPTION_NONE}; use crate::utils::sugg::Sugg; -use crate::utils::{higher, match_def_path, match_type, span_lint_and_then, SpanlessEq}; +use crate::utils::{ + higher, match_def_path, match_qpath, match_type, snippet_with_applicability, span_lint_and_then, SpanlessEq, +}; declare_clippy_lint! { /// **What it does:** Checks for expressions that could be replaced by the question mark operator. @@ -82,7 +84,7 @@ impl QuestionMark { |db| { db.span_suggestion( expr.span, - "replace_it_with", + "replace it with", replacement_str, Applicability::MaybeIncorrect, // snippet ); @@ -93,6 +95,52 @@ impl QuestionMark { } } + fn check_if_let_some_and_early_return_none(cx: &LateContext<'_, '_>, expr: &Expr<'_>) { + if_chain! { + if let ExprKind::Match(subject, arms, source) = &expr.kind; + if *source == MatchSource::IfLetDesugar { contains_else_clause: true }; + if Self::is_option(cx, subject); + + if let PatKind::TupleStruct(path1, fields, None) = &arms[0].pat.kind; + if match_qpath(path1, &["Some"]); + if let PatKind::Binding(annot, _, bind, _) = &fields[0].kind; + let by_ref = matches!(annot, BindingAnnotation::Ref | BindingAnnotation::RefMut); + + if let ExprKind::Block(block, None) = &arms[0].body.kind; + if block.stmts.is_empty(); + if let Some(trailing_expr) = &block.expr; + if let ExprKind::Path(path) = &trailing_expr.kind; + if match_qpath(path, &[&bind.as_str()]); + + if let PatKind::Wild = arms[1].pat.kind; + if Self::expression_returns_none(cx, arms[1].body); + then { + let mut applicability = Applicability::MachineApplicable; + let receiver_str = snippet_with_applicability(cx, subject.span, "..", &mut applicability); + let replacement = format!( + "{}{}?", + receiver_str, + if by_ref { ".as_ref()" } else { "" }, + ); + + span_lint_and_then( + cx, + QUESTION_MARK, + expr.span, + "this if-let-else may be rewritten with the `?` operator", + |db| { + db.span_suggestion( + expr.span, + "replace it with", + replacement, + applicability, + ); + } + ) + } + } + } + fn moves_by_default(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool { let expr_ty = cx.tables.expr_ty(expression); @@ -158,5 +206,6 @@ impl QuestionMark { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for QuestionMark { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { Self::check_is_none_and_early_return_none(cx, expr); + Self::check_if_let_some_and_early_return_none(cx, expr); } } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index f90867605aa1..58a909c845d6 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1698,12 +1698,7 @@ fn detect_absurd_comparison<'a, 'tcx>( return None; } - let normalized = normalize_comparison(op, lhs, rhs); - let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized { - val - } else { - return None; - }; + let (rel, normalized_lhs, normalized_rhs) = normalize_comparison(op, lhs, rhs)?; let lx = detect_extreme_expr(cx, normalized_lhs); let rx = detect_extreme_expr(cx, normalized_rhs); diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index 57237c52e8c9..77aa3976b79f 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -58,6 +58,12 @@ impl CopyStruct { self.opt }; + let _ = if let Some(x) = self.opt { + x + } else { + return None; + }; + self.opt } } @@ -90,6 +96,26 @@ impl MoveStruct { } Some(Vec::new()) } + + pub fn if_let_ref_func(self) -> Option> { + let mut v: &Vec<_> = if let Some(ref v) = self.opt { + v + } else { + return None; + }; + + Some(v.clone()) + } + + pub fn if_let_mov_func(self) -> Option> { + let mut v = if let Some(v) = self.opt { + v + } else { + return None; + }; + + Some(v) + } } fn main() { diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index 522501d58c66..dabba9842e48 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -4,7 +4,7 @@ error: this block may be rewritten with the `?` operator LL | / if a.is_none() { LL | | return None; LL | | } - | |_____^ help: replace_it_with: `a?;` + | |_____^ help: replace it with: `a?;` | = note: `-D clippy::question-mark` implied by `-D warnings` @@ -14,7 +14,7 @@ error: this block may be rewritten with the `?` operator LL | / if (self.opt).is_none() { LL | | return None; LL | | } - | |_________^ help: replace_it_with: `(self.opt)?;` + | |_________^ help: replace it with: `(self.opt)?;` error: this block may be rewritten with the `?` operator --> $DIR/question_mark.rs:51:9 @@ -22,7 +22,7 @@ error: this block may be rewritten with the `?` operator LL | / if self.opt.is_none() { LL | | return None LL | | } - | |_________^ help: replace_it_with: `self.opt?;` + | |_________^ help: replace it with: `self.opt?;` error: this block may be rewritten with the `?` operator --> $DIR/question_mark.rs:55:17 @@ -33,31 +33,64 @@ LL | | return None; LL | | } else { LL | | self.opt LL | | }; - | |_________^ help: replace_it_with: `Some(self.opt?)` + | |_________^ help: replace it with: `Some(self.opt?)` + +error: this if-let-else may be rewritten with the `?` operator + --> $DIR/question_mark.rs:61:17 + | +LL | let _ = if let Some(x) = self.opt { + | _________________^ +LL | | x +LL | | } else { +LL | | return None; +LL | | }; + | |_________^ help: replace it with: `self.opt?` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:72:9 + --> $DIR/question_mark.rs:78:9 | LL | / if self.opt.is_none() { LL | | return None; LL | | } - | |_________^ help: replace_it_with: `self.opt.as_ref()?;` + | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:80:9 + --> $DIR/question_mark.rs:86:9 | LL | / if self.opt.is_none() { LL | | return None; LL | | } - | |_________^ help: replace_it_with: `self.opt.as_ref()?;` + | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:88:9 + --> $DIR/question_mark.rs:94:9 | LL | / if self.opt.is_none() { LL | | return None; LL | | } - | |_________^ help: replace_it_with: `self.opt.as_ref()?;` + | |_________^ help: replace it with: `self.opt.as_ref()?;` + +error: this if-let-else may be rewritten with the `?` operator + --> $DIR/question_mark.rs:101:30 + | +LL | let mut v: &Vec<_> = if let Some(ref v) = self.opt { + | ______________________________^ +LL | | v +LL | | } else { +LL | | return None; +LL | | }; + | |_________^ help: replace it with: `self.opt.as_ref()?` + +error: this if-let-else may be rewritten with the `?` operator + --> $DIR/question_mark.rs:111:21 + | +LL | let mut v = if let Some(v) = self.opt { + | _____________________^ +LL | | v +LL | | } else { +LL | | return None; +LL | | }; + | |_________^ help: replace it with: `self.opt?` -error: aborting due to 7 previous errors +error: aborting due to 10 previous errors From 246709f89e0e8050ed714dca2155adc4e8d3ab80 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Wed, 4 Mar 2020 17:21:07 +0900 Subject: [PATCH 174/243] run-rustfix --- clippy_lints/src/question_mark.rs | 5 +- tests/ui/question_mark.fixed | 113 ++++++++++++++++++++++++++++++ tests/ui/question_mark.rs | 8 ++- tests/ui/question_mark.stderr | 28 ++++---- 4 files changed, 136 insertions(+), 18 deletions(-) create mode 100644 tests/ui/question_mark.fixed diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 5ad580aa052b..3b030f95dc92 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -57,7 +57,8 @@ impl QuestionMark { if Self::is_option(cx, subject); then { - let receiver_str = &Sugg::hir(cx, subject, ".."); + let mut applicability = Applicability::MachineApplicable; + let receiver_str = snippet_with_applicability(cx, subject.span, "..", &mut applicability); let mut replacement: Option = None; if let Some(else_) = else_ { if_chain! { @@ -86,7 +87,7 @@ impl QuestionMark { expr.span, "replace it with", replacement_str, - Applicability::MaybeIncorrect, // snippet + applicability, ); } ) diff --git a/tests/ui/question_mark.fixed b/tests/ui/question_mark.fixed new file mode 100644 index 000000000000..2c3e4989d534 --- /dev/null +++ b/tests/ui/question_mark.fixed @@ -0,0 +1,113 @@ +// run-rustfix +#![allow(unreachable_code)] + +fn some_func(a: Option) -> Option { + a?; + + a +} + +fn some_other_func(a: Option) -> Option { + if a.is_none() { + return None; + } else { + return Some(0); + } + unreachable!() +} + +pub enum SeemsOption { + Some(T), + None, +} + +impl SeemsOption { + pub fn is_none(&self) -> bool { + match *self { + SeemsOption::None => true, + SeemsOption::Some(_) => false, + } + } +} + +fn returns_something_similar_to_option(a: SeemsOption) -> SeemsOption { + if a.is_none() { + return SeemsOption::None; + } + + a +} + +pub struct CopyStruct { + pub opt: Option, +} + +impl CopyStruct { + #[rustfmt::skip] + pub fn func(&self) -> Option { + (self.opt)?; + + self.opt?; + + let _ = Some(self.opt?); + + let _ = self.opt?; + + self.opt + } +} + +#[derive(Clone)] +pub struct MoveStruct { + pub opt: Option>, +} + +impl MoveStruct { + pub fn ref_func(&self) -> Option> { + self.opt.as_ref()?; + + self.opt.clone() + } + + pub fn mov_func_reuse(self) -> Option> { + self.opt.as_ref()?; + + self.opt + } + + pub fn mov_func_no_use(self) -> Option> { + self.opt.as_ref()?; + Some(Vec::new()) + } + + pub fn if_let_ref_func(self) -> Option> { + let v: &Vec<_> = self.opt.as_ref()?; + + Some(v.clone()) + } + + pub fn if_let_mov_func(self) -> Option> { + let v = self.opt?; + + Some(v) + } +} + +fn main() { + some_func(Some(42)); + some_func(None); + some_other_func(Some(42)); + + let copy_struct = CopyStruct { opt: Some(54) }; + copy_struct.func(); + + let move_struct = MoveStruct { + opt: Some(vec![42, 1337]), + }; + move_struct.ref_func(); + move_struct.clone().mov_func_reuse(); + move_struct.mov_func_no_use(); + + let so = SeemsOption::Some(45); + returns_something_similar_to_option(so); +} diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index 77aa3976b79f..24df76344356 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -1,3 +1,6 @@ +// run-rustfix +#![allow(unreachable_code)] + fn some_func(a: Option) -> Option { if a.is_none() { return None; @@ -98,7 +101,7 @@ impl MoveStruct { } pub fn if_let_ref_func(self) -> Option> { - let mut v: &Vec<_> = if let Some(ref v) = self.opt { + let v: &Vec<_> = if let Some(ref v) = self.opt { v } else { return None; @@ -108,7 +111,7 @@ impl MoveStruct { } pub fn if_let_mov_func(self) -> Option> { - let mut v = if let Some(v) = self.opt { + let v = if let Some(v) = self.opt { v } else { return None; @@ -121,6 +124,7 @@ impl MoveStruct { fn main() { some_func(Some(42)); some_func(None); + some_other_func(Some(42)); let copy_struct = CopyStruct { opt: Some(54) }; copy_struct.func(); diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index dabba9842e48..97741069b50a 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -1,5 +1,5 @@ error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:2:5 + --> $DIR/question_mark.rs:5:5 | LL | / if a.is_none() { LL | | return None; @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::question-mark` implied by `-D warnings` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:47:9 + --> $DIR/question_mark.rs:50:9 | LL | / if (self.opt).is_none() { LL | | return None; @@ -17,7 +17,7 @@ LL | | } | |_________^ help: replace it with: `(self.opt)?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:51:9 + --> $DIR/question_mark.rs:54:9 | LL | / if self.opt.is_none() { LL | | return None @@ -25,7 +25,7 @@ LL | | } | |_________^ help: replace it with: `self.opt?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:55:17 + --> $DIR/question_mark.rs:58:17 | LL | let _ = if self.opt.is_none() { | _________________^ @@ -36,7 +36,7 @@ LL | | }; | |_________^ help: replace it with: `Some(self.opt?)` error: this if-let-else may be rewritten with the `?` operator - --> $DIR/question_mark.rs:61:17 + --> $DIR/question_mark.rs:64:17 | LL | let _ = if let Some(x) = self.opt { | _________________^ @@ -47,7 +47,7 @@ LL | | }; | |_________^ help: replace it with: `self.opt?` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:78:9 + --> $DIR/question_mark.rs:81:9 | LL | / if self.opt.is_none() { LL | | return None; @@ -55,7 +55,7 @@ LL | | } | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:86:9 + --> $DIR/question_mark.rs:89:9 | LL | / if self.opt.is_none() { LL | | return None; @@ -63,7 +63,7 @@ LL | | } | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this block may be rewritten with the `?` operator - --> $DIR/question_mark.rs:94:9 + --> $DIR/question_mark.rs:97:9 | LL | / if self.opt.is_none() { LL | | return None; @@ -71,10 +71,10 @@ LL | | } | |_________^ help: replace it with: `self.opt.as_ref()?;` error: this if-let-else may be rewritten with the `?` operator - --> $DIR/question_mark.rs:101:30 + --> $DIR/question_mark.rs:104:26 | -LL | let mut v: &Vec<_> = if let Some(ref v) = self.opt { - | ______________________________^ +LL | let v: &Vec<_> = if let Some(ref v) = self.opt { + | __________________________^ LL | | v LL | | } else { LL | | return None; @@ -82,10 +82,10 @@ LL | | }; | |_________^ help: replace it with: `self.opt.as_ref()?` error: this if-let-else may be rewritten with the `?` operator - --> $DIR/question_mark.rs:111:21 + --> $DIR/question_mark.rs:114:17 | -LL | let mut v = if let Some(v) = self.opt { - | _____________________^ +LL | let v = if let Some(v) = self.opt { + | _________________^ LL | | v LL | | } else { LL | | return None; From 9ff4581cd31ede554eabf97b47df033c39752b23 Mon Sep 17 00:00:00 2001 From: mlegner Date: Mon, 2 Mar 2020 09:49:33 +0100 Subject: [PATCH 175/243] Test for unnecessary_cast of hex int literal. --- tests/ui/unnecessary_cast_fixable.fixed | 1 + tests/ui/unnecessary_cast_fixable.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/ui/unnecessary_cast_fixable.fixed b/tests/ui/unnecessary_cast_fixable.fixed index 8c659df831e3..578ad5c8d33b 100644 --- a/tests/ui/unnecessary_cast_fixable.fixed +++ b/tests/ui/unnecessary_cast_fixable.fixed @@ -14,4 +14,5 @@ fn main() { &v as &[i32]; 1.0 as f64; 1 as u64; + 0x42 as f32; } diff --git a/tests/ui/unnecessary_cast_fixable.rs b/tests/ui/unnecessary_cast_fixable.rs index 7bab5540c42f..b3518231abeb 100644 --- a/tests/ui/unnecessary_cast_fixable.rs +++ b/tests/ui/unnecessary_cast_fixable.rs @@ -14,4 +14,5 @@ fn main() { &v as &[i32]; 1.0 as f64; 1 as u64; + 0x42 as f32; } From 6673cc8329a2bc1395cf6c3c1ec194cbd83b567e Mon Sep 17 00:00:00 2001 From: mlegner Date: Mon, 2 Mar 2020 22:44:32 +0100 Subject: [PATCH 176/243] Resolve false positives for hex int cast. --- clippy_lints/src/literal_representation.rs | 14 +++++---- clippy_lints/src/types.rs | 33 +++++++++++++--------- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 66435f954231..43b2c4e78b47 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -131,7 +131,7 @@ pub fn format_numeric_literal(lit: &str, type_suffix: Option<&str>, float: bool) #[derive(Debug)] pub(super) struct NumericLiteral<'a> { /// Which radix the literal was represented in. - radix: Radix, + pub radix: Radix, /// The radix prefix, if present. prefix: Option<&'a str>, @@ -147,16 +147,20 @@ pub(super) struct NumericLiteral<'a> { } impl<'a> NumericLiteral<'a> { - fn from_lit(src: &'a str, lit: &Lit) -> Option> { - if lit.kind.is_numeric() && src.chars().next().map_or(false, |c| c.is_digit(10)) { - let (unsuffixed, suffix) = split_suffix(&src, &lit.kind); - let float = if let LitKind::Float(..) = lit.kind { true } else { false }; + pub fn from_lit_kind(src: &'a str, lit_kind: &LitKind) -> Option> { + if lit_kind.is_numeric() && src.chars().next().map_or(false, |c| c.is_digit(10)) { + let (unsuffixed, suffix) = split_suffix(&src, lit_kind); + let float = if let LitKind::Float(..) = lit_kind { true } else { false }; Some(NumericLiteral::new(unsuffixed, suffix, float)) } else { None } } + fn from_lit(src: &'a str, lit: &Lit) -> Option> { + NumericLiteral::from_lit_kind(src, &lit.kind) + } + #[must_use] fn new(lit: &'a str, suffix: Option<&'a str>, float: bool) -> Self { // Determine delimiter for radix prefix, if present, and radix. diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index f90867605aa1..ada5c8f2d9f9 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -27,6 +27,7 @@ use rustc_target::spec::abi::Abi; use rustc_typeck::hir_ty_to_ty; use crate::consts::{constant, Constant}; +use crate::literal_representation::{NumericLiteral, Radix}; use crate::utils::paths; use crate::utils::{ clip, comparisons, differing_macro_contexts, higher, in_constant, int_bits, last_path_segment, match_def_path, @@ -1210,21 +1211,27 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Casts { let (cast_from, cast_to) = (cx.tables.expr_ty(ex), cx.tables.expr_ty(expr)); lint_fn_to_numeric_cast(cx, expr, ex, cast_from, cast_to); if let ExprKind::Lit(ref lit) = ex.kind { - if let LitKind::Int(n, _) = lit.node { - if cast_to.is_floating_point() { + if_chain! { + if let LitKind::Int(n, _) = lit.node; + if let Some(src) = snippet_opt(cx, lit.span); + if cast_to.is_floating_point(); + then { let from_nbits = 128 - n.leading_zeros(); let to_nbits = fp_ty_mantissa_nbits(cast_to); - if from_nbits != 0 && to_nbits != 0 && from_nbits <= to_nbits { - span_lint_and_sugg( - cx, - UNNECESSARY_CAST, - expr.span, - &format!("casting integer literal to `{}` is unnecessary", cast_to), - "try", - format!("{}_{}", n, cast_to), - Applicability::MachineApplicable, - ); - return; + if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) { + if from_nbits != 0 && to_nbits != 0 && from_nbits <= to_nbits && + num_lit.radix != Radix::Hexadecimal { + span_lint_and_sugg( + cx, + UNNECESSARY_CAST, + expr.span, + &format!("casting integer literal to `{}` is unnecessary", cast_to), + "try", + format!("{}_{}", n, cast_to), + Applicability::MachineApplicable, + ); + return; + } } } } From 73deb723ddb5ff39d830e698136f081b47f3a94b Mon Sep 17 00:00:00 2001 From: mlegner Date: Tue, 3 Mar 2020 17:05:09 +0100 Subject: [PATCH 177/243] Included binary and octal cases. --- clippy_lints/src/literal_representation.rs | 14 +++++++++----- clippy_lints/src/types.rs | 5 ++--- tests/ui/unnecessary_cast_fixable.fixed | 7 ++++++- tests/ui/unnecessary_cast_fixable.rs | 7 ++++++- 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 43b2c4e78b47..a42d240ba642 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -131,7 +131,7 @@ pub fn format_numeric_literal(lit: &str, type_suffix: Option<&str>, float: bool) #[derive(Debug)] pub(super) struct NumericLiteral<'a> { /// Which radix the literal was represented in. - pub radix: Radix, + radix: Radix, /// The radix prefix, if present. prefix: Option<&'a str>, @@ -147,6 +147,10 @@ pub(super) struct NumericLiteral<'a> { } impl<'a> NumericLiteral<'a> { + fn from_lit(src: &'a str, lit: &Lit) -> Option> { + NumericLiteral::from_lit_kind(src, &lit.kind) + } + pub fn from_lit_kind(src: &'a str, lit_kind: &LitKind) -> Option> { if lit_kind.is_numeric() && src.chars().next().map_or(false, |c| c.is_digit(10)) { let (unsuffixed, suffix) = split_suffix(&src, lit_kind); @@ -157,10 +161,6 @@ impl<'a> NumericLiteral<'a> { } } - fn from_lit(src: &'a str, lit: &Lit) -> Option> { - NumericLiteral::from_lit_kind(src, &lit.kind) - } - #[must_use] fn new(lit: &'a str, suffix: Option<&'a str>, float: bool) -> Self { // Determine delimiter for radix prefix, if present, and radix. @@ -199,6 +199,10 @@ impl<'a> NumericLiteral<'a> { } } + pub fn is_decimal(&self) -> bool { + self.radix == Radix::Decimal + } + fn split_digit_parts(digits: &str, float: bool) -> (&str, Option<&str>, Option<(char, &str)>) { let mut integer = digits; let mut fraction = None; diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index ada5c8f2d9f9..0ecd03605b2a 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -27,7 +27,7 @@ use rustc_target::spec::abi::Abi; use rustc_typeck::hir_ty_to_ty; use crate::consts::{constant, Constant}; -use crate::literal_representation::{NumericLiteral, Radix}; +use crate::literal_representation::NumericLiteral; use crate::utils::paths; use crate::utils::{ clip, comparisons, differing_macro_contexts, higher, in_constant, int_bits, last_path_segment, match_def_path, @@ -1219,8 +1219,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Casts { let from_nbits = 128 - n.leading_zeros(); let to_nbits = fp_ty_mantissa_nbits(cast_to); if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) { - if from_nbits != 0 && to_nbits != 0 && from_nbits <= to_nbits && - num_lit.radix != Radix::Hexadecimal { + if from_nbits != 0 && to_nbits != 0 && from_nbits <= to_nbits && num_lit.is_decimal() { span_lint_and_sugg( cx, UNNECESSARY_CAST, diff --git a/tests/ui/unnecessary_cast_fixable.fixed b/tests/ui/unnecessary_cast_fixable.fixed index 578ad5c8d33b..fb89a9fce3d5 100644 --- a/tests/ui/unnecessary_cast_fixable.fixed +++ b/tests/ui/unnecessary_cast_fixable.fixed @@ -14,5 +14,10 @@ fn main() { &v as &[i32]; 1.0 as f64; 1 as u64; - 0x42 as f32; + 0x10 as f32; + 0o10 as f32; + 0b10 as f32; + 0x11 as f64; + 0o11 as f64; + 0b11 as f64; } diff --git a/tests/ui/unnecessary_cast_fixable.rs b/tests/ui/unnecessary_cast_fixable.rs index b3518231abeb..4a0c8620dc13 100644 --- a/tests/ui/unnecessary_cast_fixable.rs +++ b/tests/ui/unnecessary_cast_fixable.rs @@ -14,5 +14,10 @@ fn main() { &v as &[i32]; 1.0 as f64; 1 as u64; - 0x42 as f32; + 0x10 as f32; + 0o10 as f32; + 0b10 as f32; + 0x11 as f64; + 0o11 as f64; + 0b11 as f64; } From d14fdc0203b8290df9527aa62c25a64922f8126a Mon Sep 17 00:00:00 2001 From: mlegner Date: Tue, 3 Mar 2020 17:58:37 +0100 Subject: [PATCH 178/243] Move NumericLiteral to its own module. --- clippy_lints/src/float_literal.rs | 7 +- clippy_lints/src/floating_point_arithmetic.rs | 6 +- clippy_lints/src/literal_representation.rs | 234 +----------------- clippy_lints/src/types.rs | 7 +- clippy_lints/src/utils/mod.rs | 1 + clippy_lints/src/utils/numeric_literal.rs | 227 +++++++++++++++++ clippy_lints/src/utils/sugg.rs | 2 - 7 files changed, 243 insertions(+), 241 deletions(-) create mode 100644 clippy_lints/src/utils/numeric_literal.rs diff --git a/clippy_lints/src/float_literal.rs b/clippy_lints/src/float_literal.rs index 30d4b25318f7..55a9f61242b4 100644 --- a/clippy_lints/src/float_literal.rs +++ b/clippy_lints/src/float_literal.rs @@ -1,5 +1,4 @@ -use crate::utils::span_lint_and_sugg; -use crate::utils::sugg::format_numeric_literal; +use crate::utils::{numeric_literal, span_lint_and_sugg}; use if_chain::if_chain; use rustc::ty; use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; @@ -109,7 +108,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatLiteral { expr.span, "literal cannot be represented as the underlying type without loss of precision", "consider changing the type or replacing it with", - format_numeric_literal(&float_str, type_suffix, true), + numeric_literal::format(&float_str, type_suffix, true), Applicability::MachineApplicable, ); } @@ -120,7 +119,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatLiteral { expr.span, "float has excessive precision", "consider changing the type or truncating it to", - format_numeric_literal(&float_str, type_suffix, true), + numeric_literal::format(&float_str, type_suffix, true), Applicability::MachineApplicable, ); } diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 0fcfb7b88497..cee14dc893b5 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -2,7 +2,7 @@ use crate::consts::{ constant, constant_simple, Constant, Constant::{F32, F64}, }; -use crate::utils::{higher, span_lint_and_sugg, sugg, SpanlessEq}; +use crate::utils::{higher, numeric_literal, span_lint_and_sugg, sugg, SpanlessEq}; use if_chain::if_chain; use rustc::ty; use rustc_errors::Applicability; @@ -14,7 +14,7 @@ use rustc_span::source_map::Spanned; use rustc_ast::ast; use std::f32::consts as f32_consts; use std::f64::consts as f64_consts; -use sugg::{format_numeric_literal, Sugg}; +use sugg::Sugg; declare_clippy_lint! { /// **What it does:** Looks for floating-point expressions that @@ -276,7 +276,7 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { format!( "{}.powi({})", Sugg::hir(cx, &args[0], ".."), - format_numeric_literal(&exponent.to_string(), None, false) + numeric_literal::format(&exponent.to_string(), None, false) ), ) } else { diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index a42d240ba642..9e6b63fafd09 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -1,10 +1,14 @@ //! Lints concerned with the grouping of digits with underscores in integral or //! floating-point literal expressions. -use crate::utils::{in_macro, snippet_opt, span_lint_and_sugg}; +use crate::utils::{ + in_macro, + numeric_literal::{NumericLiteral, Radix}, + snippet_opt, span_lint_and_sugg, +}; use if_chain::if_chain; use rustc::lint::in_external_macro; -use rustc_ast::ast::{Expr, ExprKind, Lit, LitFloatType, LitIntType, LitKind}; +use rustc_ast::ast::{Expr, ExprKind, Lit, LitKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; @@ -103,232 +107,6 @@ declare_clippy_lint! { "using decimal representation when hexadecimal would be better" } -#[derive(Debug, PartialEq)] -pub(super) enum Radix { - Binary, - Octal, - Decimal, - Hexadecimal, -} - -impl Radix { - /// Returns a reasonable digit group size for this radix. - #[must_use] - fn suggest_grouping(&self) -> usize { - match *self { - Self::Binary | Self::Hexadecimal => 4, - Self::Octal | Self::Decimal => 3, - } - } -} - -/// A helper method to format numeric literals with digit grouping. -/// `lit` must be a valid numeric literal without suffix. -pub fn format_numeric_literal(lit: &str, type_suffix: Option<&str>, float: bool) -> String { - NumericLiteral::new(lit, type_suffix, float).format() -} - -#[derive(Debug)] -pub(super) struct NumericLiteral<'a> { - /// Which radix the literal was represented in. - radix: Radix, - /// The radix prefix, if present. - prefix: Option<&'a str>, - - /// The integer part of the number. - integer: &'a str, - /// The fraction part of the number. - fraction: Option<&'a str>, - /// The character used as exponent seperator (b'e' or b'E') and the exponent part. - exponent: Option<(char, &'a str)>, - - /// The type suffix, including preceding underscore if present. - suffix: Option<&'a str>, -} - -impl<'a> NumericLiteral<'a> { - fn from_lit(src: &'a str, lit: &Lit) -> Option> { - NumericLiteral::from_lit_kind(src, &lit.kind) - } - - pub fn from_lit_kind(src: &'a str, lit_kind: &LitKind) -> Option> { - if lit_kind.is_numeric() && src.chars().next().map_or(false, |c| c.is_digit(10)) { - let (unsuffixed, suffix) = split_suffix(&src, lit_kind); - let float = if let LitKind::Float(..) = lit_kind { true } else { false }; - Some(NumericLiteral::new(unsuffixed, suffix, float)) - } else { - None - } - } - - #[must_use] - fn new(lit: &'a str, suffix: Option<&'a str>, float: bool) -> Self { - // Determine delimiter for radix prefix, if present, and radix. - let radix = if lit.starts_with("0x") { - Radix::Hexadecimal - } else if lit.starts_with("0b") { - Radix::Binary - } else if lit.starts_with("0o") { - Radix::Octal - } else { - Radix::Decimal - }; - - // Grab part of the literal after prefix, if present. - let (prefix, mut sans_prefix) = if let Radix::Decimal = radix { - (None, lit) - } else { - let (p, s) = lit.split_at(2); - (Some(p), s) - }; - - if suffix.is_some() && sans_prefix.ends_with('_') { - // The '_' before the suffix isn't part of the digits - sans_prefix = &sans_prefix[..sans_prefix.len() - 1]; - } - - let (integer, fraction, exponent) = Self::split_digit_parts(sans_prefix, float); - - Self { - radix, - prefix, - integer, - fraction, - exponent, - suffix, - } - } - - pub fn is_decimal(&self) -> bool { - self.radix == Radix::Decimal - } - - fn split_digit_parts(digits: &str, float: bool) -> (&str, Option<&str>, Option<(char, &str)>) { - let mut integer = digits; - let mut fraction = None; - let mut exponent = None; - - if float { - for (i, c) in digits.char_indices() { - match c { - '.' => { - integer = &digits[..i]; - fraction = Some(&digits[i + 1..]); - }, - 'e' | 'E' => { - if integer.len() > i { - integer = &digits[..i]; - } else { - fraction = Some(&digits[integer.len() + 1..i]); - }; - exponent = Some((c, &digits[i + 1..])); - break; - }, - _ => {}, - } - } - } - - (integer, fraction, exponent) - } - - /// Returns literal formatted in a sensible way. - fn format(&self) -> String { - let mut output = String::new(); - - if let Some(prefix) = self.prefix { - output.push_str(prefix); - } - - let group_size = self.radix.suggest_grouping(); - - Self::group_digits( - &mut output, - self.integer, - group_size, - true, - self.radix == Radix::Hexadecimal, - ); - - if let Some(fraction) = self.fraction { - output.push('.'); - Self::group_digits(&mut output, fraction, group_size, false, false); - } - - if let Some((separator, exponent)) = self.exponent { - output.push(separator); - Self::group_digits(&mut output, exponent, group_size, true, false); - } - - if let Some(suffix) = self.suffix { - output.push('_'); - output.push_str(suffix); - } - - output - } - - fn group_digits(output: &mut String, input: &str, group_size: usize, partial_group_first: bool, pad: bool) { - debug_assert!(group_size > 0); - - let mut digits = input.chars().filter(|&c| c != '_'); - - let first_group_size; - - if partial_group_first { - first_group_size = (digits.clone().count() - 1) % group_size + 1; - if pad { - for _ in 0..group_size - first_group_size { - output.push('0'); - } - } - } else { - first_group_size = group_size; - } - - for _ in 0..first_group_size { - if let Some(digit) = digits.next() { - output.push(digit); - } - } - - for (c, i) in digits.zip((0..group_size).cycle()) { - if i == 0 { - output.push('_'); - } - output.push(c); - } - } -} - -fn split_suffix<'a>(src: &'a str, lit_kind: &LitKind) -> (&'a str, Option<&'a str>) { - debug_assert!(lit_kind.is_numeric()); - if let Some(suffix_length) = lit_suffix_length(lit_kind) { - let (unsuffixed, suffix) = src.split_at(src.len() - suffix_length); - (unsuffixed, Some(suffix)) - } else { - (src, None) - } -} - -fn lit_suffix_length(lit_kind: &LitKind) -> Option { - debug_assert!(lit_kind.is_numeric()); - let suffix = match lit_kind { - LitKind::Int(_, int_lit_kind) => match int_lit_kind { - LitIntType::Signed(int_ty) => Some(int_ty.name_str()), - LitIntType::Unsigned(uint_ty) => Some(uint_ty.name_str()), - LitIntType::Unsuffixed => None, - }, - LitKind::Float(_, float_lit_kind) => match float_lit_kind { - LitFloatType::Suffixed(float_ty) => Some(float_ty.name_str()), - LitFloatType::Unsuffixed => None, - }, - _ => None, - }; - - suffix.map(str::len) -} - enum WarningType { UnreadableLiteral, InconsistentDigitGrouping, diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 0ecd03605b2a..9bb054ec4e28 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -27,13 +27,12 @@ use rustc_target::spec::abi::Abi; use rustc_typeck::hir_ty_to_ty; use crate::consts::{constant, Constant}; -use crate::literal_representation::NumericLiteral; use crate::utils::paths; use crate::utils::{ clip, comparisons, differing_macro_contexts, higher, in_constant, int_bits, last_path_segment, match_def_path, - match_path, method_chain_args, multispan_sugg, qpath_res, same_tys, sext, snippet, snippet_opt, - snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg, - span_lint_and_then, unsext, + match_path, method_chain_args, multispan_sugg, numeric_literal::NumericLiteral, qpath_res, same_tys, sext, snippet, + snippet_opt, snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_help, + span_lint_and_sugg, span_lint_and_then, unsext, }; declare_clippy_lint! { diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 640cce113806..dc8775b43b19 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -12,6 +12,7 @@ pub mod higher; mod hir_utils; pub mod inspector; pub mod internal_lints; +pub mod numeric_literal; pub mod paths; pub mod ptr; pub mod sugg; diff --git a/clippy_lints/src/utils/numeric_literal.rs b/clippy_lints/src/utils/numeric_literal.rs new file mode 100644 index 000000000000..8b3492724e10 --- /dev/null +++ b/clippy_lints/src/utils/numeric_literal.rs @@ -0,0 +1,227 @@ +use rustc_ast::ast::{Lit, LitFloatType, LitIntType, LitKind}; + +#[derive(Debug, PartialEq)] +pub(crate) enum Radix { + Binary, + Octal, + Decimal, + Hexadecimal, +} + +impl Radix { + /// Returns a reasonable digit group size for this radix. + #[must_use] + fn suggest_grouping(&self) -> usize { + match *self { + Self::Binary | Self::Hexadecimal => 4, + Self::Octal | Self::Decimal => 3, + } + } +} + +/// A helper method to format numeric literals with digit grouping. +/// `lit` must be a valid numeric literal without suffix. +pub fn format(lit: &str, type_suffix: Option<&str>, float: bool) -> String { + NumericLiteral::new(lit, type_suffix, float).format() +} + +#[derive(Debug)] +pub(crate) struct NumericLiteral<'a> { + /// Which radix the literal was represented in. + pub radix: Radix, + /// The radix prefix, if present. + pub prefix: Option<&'a str>, + + /// The integer part of the number. + pub integer: &'a str, + /// The fraction part of the number. + pub fraction: Option<&'a str>, + /// The character used as exponent seperator (b'e' or b'E') and the exponent part. + pub exponent: Option<(char, &'a str)>, + + /// The type suffix, including preceding underscore if present. + pub suffix: Option<&'a str>, +} + +impl<'a> NumericLiteral<'a> { + pub fn from_lit(src: &'a str, lit: &Lit) -> Option> { + NumericLiteral::from_lit_kind(src, &lit.kind) + } + + pub fn from_lit_kind(src: &'a str, lit_kind: &LitKind) -> Option> { + if lit_kind.is_numeric() && src.chars().next().map_or(false, |c| c.is_digit(10)) { + let (unsuffixed, suffix) = split_suffix(&src, lit_kind); + let float = if let LitKind::Float(..) = lit_kind { true } else { false }; + Some(NumericLiteral::new(unsuffixed, suffix, float)) + } else { + None + } + } + + #[must_use] + pub fn new(lit: &'a str, suffix: Option<&'a str>, float: bool) -> Self { + // Determine delimiter for radix prefix, if present, and radix. + let radix = if lit.starts_with("0x") { + Radix::Hexadecimal + } else if lit.starts_with("0b") { + Radix::Binary + } else if lit.starts_with("0o") { + Radix::Octal + } else { + Radix::Decimal + }; + + // Grab part of the literal after prefix, if present. + let (prefix, mut sans_prefix) = if let Radix::Decimal = radix { + (None, lit) + } else { + let (p, s) = lit.split_at(2); + (Some(p), s) + }; + + if suffix.is_some() && sans_prefix.ends_with('_') { + // The '_' before the suffix isn't part of the digits + sans_prefix = &sans_prefix[..sans_prefix.len() - 1]; + } + + let (integer, fraction, exponent) = Self::split_digit_parts(sans_prefix, float); + + Self { + radix, + prefix, + integer, + fraction, + exponent, + suffix, + } + } + + pub fn is_decimal(&self) -> bool { + self.radix == Radix::Decimal + } + + pub fn split_digit_parts(digits: &str, float: bool) -> (&str, Option<&str>, Option<(char, &str)>) { + let mut integer = digits; + let mut fraction = None; + let mut exponent = None; + + if float { + for (i, c) in digits.char_indices() { + match c { + '.' => { + integer = &digits[..i]; + fraction = Some(&digits[i + 1..]); + }, + 'e' | 'E' => { + if integer.len() > i { + integer = &digits[..i]; + } else { + fraction = Some(&digits[integer.len() + 1..i]); + }; + exponent = Some((c, &digits[i + 1..])); + break; + }, + _ => {}, + } + } + } + + (integer, fraction, exponent) + } + + /// Returns literal formatted in a sensible way. + pub fn format(&self) -> String { + let mut output = String::new(); + + if let Some(prefix) = self.prefix { + output.push_str(prefix); + } + + let group_size = self.radix.suggest_grouping(); + + Self::group_digits( + &mut output, + self.integer, + group_size, + true, + self.radix == Radix::Hexadecimal, + ); + + if let Some(fraction) = self.fraction { + output.push('.'); + Self::group_digits(&mut output, fraction, group_size, false, false); + } + + if let Some((separator, exponent)) = self.exponent { + output.push(separator); + Self::group_digits(&mut output, exponent, group_size, true, false); + } + + if let Some(suffix) = self.suffix { + output.push('_'); + output.push_str(suffix); + } + + output + } + + pub fn group_digits(output: &mut String, input: &str, group_size: usize, partial_group_first: bool, pad: bool) { + debug_assert!(group_size > 0); + + let mut digits = input.chars().filter(|&c| c != '_'); + + let first_group_size; + + if partial_group_first { + first_group_size = (digits.clone().count() - 1) % group_size + 1; + if pad { + for _ in 0..group_size - first_group_size { + output.push('0'); + } + } + } else { + first_group_size = group_size; + } + + for _ in 0..first_group_size { + if let Some(digit) = digits.next() { + output.push(digit); + } + } + + for (c, i) in digits.zip((0..group_size).cycle()) { + if i == 0 { + output.push('_'); + } + output.push(c); + } + } +} + +fn split_suffix<'a>(src: &'a str, lit_kind: &LitKind) -> (&'a str, Option<&'a str>) { + debug_assert!(lit_kind.is_numeric()); + if let Some(suffix_length) = lit_suffix_length(lit_kind) { + let (unsuffixed, suffix) = src.split_at(src.len() - suffix_length); + (unsuffixed, Some(suffix)) + } else { + (src, None) + } +} + +fn lit_suffix_length(lit_kind: &LitKind) -> Option { + debug_assert!(lit_kind.is_numeric()); + let suffix = match lit_kind { + LitKind::Int(_, int_lit_kind) => match int_lit_kind { + LitIntType::Signed(int_ty) => Some(int_ty.name_str()), + LitIntType::Unsigned(uint_ty) => Some(uint_ty.name_str()), + LitIntType::Unsuffixed => None, + }, + LitKind::Float(_, float_lit_kind) => match float_lit_kind { + LitFloatType::Suffixed(float_ty) => Some(float_ty.name_str()), + LitFloatType::Unsuffixed => None, + }, + _ => None, + }; + + suffix.map(str::len) +} diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 05cc4f33eaed..8cf3c07a2d42 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -15,8 +15,6 @@ use std::borrow::Cow; use std::convert::TryInto; use std::fmt::Display; -pub use crate::literal_representation::format_numeric_literal; - /// A helper type to build suggestion correctly handling parenthesis. pub enum Sugg<'a> { /// An expression that never needs parenthesis such as `1337` or `[0; 42]`. From 185fa0d1b1ea7ba9677c7f3d6e2c3d5968f26539 Mon Sep 17 00:00:00 2001 From: mlegner Date: Wed, 4 Mar 2020 10:12:11 +0100 Subject: [PATCH 179/243] Simplify if_chain. --- clippy_lints/src/types.rs | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 9bb054ec4e28..f96e797217f5 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1214,23 +1214,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Casts { if let LitKind::Int(n, _) = lit.node; if let Some(src) = snippet_opt(cx, lit.span); if cast_to.is_floating_point(); + if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node); + let from_nbits = 128 - n.leading_zeros(); + let to_nbits = fp_ty_mantissa_nbits(cast_to); + if from_nbits != 0 && to_nbits != 0 && from_nbits <= to_nbits && num_lit.is_decimal(); then { - let from_nbits = 128 - n.leading_zeros(); - let to_nbits = fp_ty_mantissa_nbits(cast_to); - if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) { - if from_nbits != 0 && to_nbits != 0 && from_nbits <= to_nbits && num_lit.is_decimal() { - span_lint_and_sugg( - cx, - UNNECESSARY_CAST, - expr.span, - &format!("casting integer literal to `{}` is unnecessary", cast_to), - "try", - format!("{}_{}", n, cast_to), - Applicability::MachineApplicable, - ); - return; - } - } + span_lint_and_sugg( + cx, + UNNECESSARY_CAST, + expr.span, + &format!("casting integer literal to `{}` is unnecessary", cast_to), + "try", + format!("{}_{}", n, cast_to), + Applicability::MachineApplicable, + ); + return; } } match lit.node { From a78a1fc97bfa78eba0d276add37aad543e0e610d Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Wed, 4 Mar 2020 12:59:58 +0000 Subject: [PATCH 180/243] Apply suggestions from code review Co-Authored-By: Philipp Krones --- clippy_lints/src/question_mark.rs | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 3b030f95dc92..f054c6ef67d3 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -8,7 +8,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use crate::utils::paths::{OPTION, OPTION_NONE}; use crate::utils::sugg::Sugg; use crate::utils::{ - higher, match_def_path, match_qpath, match_type, snippet_with_applicability, span_lint_and_then, SpanlessEq, + higher, match_def_path, match_qpath, match_type, snippet_with_applicability, span_lint_and_sugg, SpanlessEq, }; declare_clippy_lint! { @@ -58,7 +58,7 @@ impl QuestionMark { then { let mut applicability = Applicability::MachineApplicable; - let receiver_str = snippet_with_applicability(cx, subject.span, "..", &mut applicability); + let receiver_str = &Sugg::hir_with_applicability(cx, subject, "..", &mut applicability); let mut replacement: Option = None; if let Some(else_) = else_ { if_chain! { @@ -77,19 +77,14 @@ impl QuestionMark { } if let Some(replacement_str) = replacement { - span_lint_and_then( + span_lint_and_sugg( cx, QUESTION_MARK, expr.span, "this block may be rewritten with the `?` operator", - |db| { - db.span_suggestion( - expr.span, - "replace it with", - replacement_str, - applicability, - ); - } + "replace it with", + replacement_str, + applicability, ) } } @@ -124,19 +119,14 @@ impl QuestionMark { if by_ref { ".as_ref()" } else { "" }, ); - span_lint_and_then( + span_lint_and_sugg( cx, QUESTION_MARK, expr.span, "this if-let-else may be rewritten with the `?` operator", - |db| { - db.span_suggestion( - expr.span, - "replace it with", - replacement, - applicability, - ); - } + "replace it with", + replacement, + applicability, ) } } From 597e02dcdf28e9cfbb7854bca38c28f2e4d15425 Mon Sep 17 00:00:00 2001 From: Devin R Date: Wed, 26 Feb 2020 07:40:31 -0500 Subject: [PATCH 181/243] warn on macro_use attr --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 4 +++ clippy_lints/src/macro_use.rs | 53 ++++++++++++++++++++++++++++++++ src/lintlist/mod.rs | 9 +++++- tests/ui/macro_use_import.rs | 11 +++++++ tests/ui/macro_use_import.stderr | 10 ++++++ 7 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 clippy_lints/src/macro_use.rs create mode 100644 tests/ui/macro_use_import.rs create mode 100644 tests/ui/macro_use_import.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d8e24943897..9ba9fdd4b8a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1209,6 +1209,7 @@ Released 2018-09-13 [`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist [`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug [`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal +[`macro_use_import`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_import [`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion [`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy [`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic diff --git a/README.md b/README.md index 6915b1bde025..8635b2b6d5a5 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 359 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 360 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 327cc56cafa5..86ab7d839054 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -234,6 +234,7 @@ pub mod let_underscore; pub mod lifetimes; pub mod literal_representation; pub mod loops; +pub mod macro_use; pub mod main_recursion; pub mod map_clone; pub mod map_unit_fn; @@ -599,6 +600,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &loops::WHILE_IMMUTABLE_CONDITION, &loops::WHILE_LET_LOOP, &loops::WHILE_LET_ON_ITERATOR, + ¯o_use::MACRO_USE_IMPORT, &main_recursion::MAIN_RECURSION, &map_clone::MAP_CLONE, &map_unit_fn::OPTION_MAP_UNIT_FN, @@ -1012,6 +1014,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(move || box excessive_bools::ExcessiveBools::new(max_struct_bools, max_fn_params_bools)); store.register_early_pass(|| box option_env_unwrap::OptionEnvUnwrap); store.register_late_pass(|| box wildcard_imports::WildcardImports); + store.register_early_pass(|| box macro_use::MacroUseImport); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1079,6 +1082,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&literal_representation::LARGE_DIGIT_GROUPS), LintId::of(&loops::EXPLICIT_INTO_ITER_LOOP), LintId::of(&loops::EXPLICIT_ITER_LOOP), + LintId::of(¯o_use::MACRO_USE_IMPORT), LintId::of(&matches::SINGLE_MATCH_ELSE), LintId::of(&methods::FILTER_MAP), LintId::of(&methods::FILTER_MAP_NEXT), diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs new file mode 100644 index 000000000000..43671d694131 --- /dev/null +++ b/clippy_lints/src/macro_use.rs @@ -0,0 +1,53 @@ +use crate::utils::{snippet, span_lint_and_sugg}; +use if_chain::if_chain; +use rustc_ast::ast; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::edition::Edition; + +declare_clippy_lint! { + /// **What it does:** Checks for `#[macro_use] use...`. + /// + /// **Why is this bad?** Since the Rust 2018 edition you can import + /// macro's directly, this is considered idiomatic. + /// + /// **Known problems:** This lint does not generate an auto-applicable suggestion. + /// + /// **Example:** + /// ```rust + /// #[macro_use] + /// use lazy_static; + /// ``` + pub MACRO_USE_IMPORT, + pedantic, + "#[macro_use] is no longer needed" +} + +declare_lint_pass!(MacroUseImport => [MACRO_USE_IMPORT]); + +impl EarlyLintPass for MacroUseImport { + fn check_item(&mut self, ecx: &EarlyContext<'_>, item: &ast::Item) { + if_chain! { + if ecx.sess.opts.edition == Edition::Edition2018; + if let ast::ItemKind::Use(use_tree) = &item.kind; + if let Some(mac_attr) = item + .attrs + .iter() + .find(|attr| attr.ident().map(|s| s.to_string()) == Some("macro_use".to_string())); + then { + let msg = "`macro_use` attributes are no longer needed in the Rust 2018 edition"; + let help = format!("use {}::", snippet(ecx, use_tree.span, "_")); + span_lint_and_sugg( + ecx, + MACRO_USE_IMPORT, + mac_attr.span, + msg, + "remove the attribute and import the macro directly, try", + help, + Applicability::HasPlaceholders, + ); + } + } + } +} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 2b93e4279f0d..1635ff7babd7 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -6,7 +6,7 @@ pub use lint::Lint; pub use lint::LINT_LEVELS; // begin lint list, do not remove this comment, it’s used in `update_lints` -pub const ALL_LINTS: [Lint; 359] = [ +pub const ALL_LINTS: [Lint; 360] = [ Lint { name: "absurd_extreme_comparisons", group: "correctness", @@ -1015,6 +1015,13 @@ pub const ALL_LINTS: [Lint; 359] = [ deprecation: None, module: "float_literal", }, + Lint { + name: "macro_use_import", + group: "pedantic", + desc: "#[macro_use] is no longer needed", + deprecation: None, + module: "macro_use", + }, Lint { name: "main_recursion", group: "style", diff --git a/tests/ui/macro_use_import.rs b/tests/ui/macro_use_import.rs new file mode 100644 index 000000000000..33ce2b524ef7 --- /dev/null +++ b/tests/ui/macro_use_import.rs @@ -0,0 +1,11 @@ +// compile-flags: --edition 2018 +#![warn(clippy::macro_use_import)] + +use std::collections::HashMap; +#[macro_use] +use std::prelude; + +fn main() { + let _ = HashMap::::new(); + println!(); +} diff --git a/tests/ui/macro_use_import.stderr b/tests/ui/macro_use_import.stderr new file mode 100644 index 000000000000..1d86ba584411 --- /dev/null +++ b/tests/ui/macro_use_import.stderr @@ -0,0 +1,10 @@ +error: `macro_use` attributes are no longer needed in the Rust 2018 edition + --> $DIR/macro_use_import.rs:5:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use std::prelude::` + | + = note: `-D clippy::macro-use-import` implied by `-D warnings` + +error: aborting due to previous error + From 57393b5106c5475dbe9f99f75013e8ea7f1988d6 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 5 Mar 2020 19:22:17 +0100 Subject: [PATCH 182/243] Rename macro_use_import -> macro_use_imports --- CHANGELOG.md | 2 +- clippy_lints/src/lib.rs | 6 +++--- clippy_lints/src/macro_use.rs | 8 ++++---- src/lintlist/mod.rs | 2 +- tests/ui/{macro_use_import.rs => macro_use_imports.rs} | 2 +- .../{macro_use_import.stderr => macro_use_imports.stderr} | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) rename tests/ui/{macro_use_import.rs => macro_use_imports.rs} (82%) rename tests/ui/{macro_use_import.stderr => macro_use_imports.stderr} (71%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ba9fdd4b8a0..c3f291bc046d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1209,7 +1209,7 @@ Released 2018-09-13 [`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist [`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug [`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal -[`macro_use_import`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_import +[`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports [`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion [`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy [`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 86ab7d839054..02c016c385dd 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -600,7 +600,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &loops::WHILE_IMMUTABLE_CONDITION, &loops::WHILE_LET_LOOP, &loops::WHILE_LET_ON_ITERATOR, - ¯o_use::MACRO_USE_IMPORT, + ¯o_use::MACRO_USE_IMPORTS, &main_recursion::MAIN_RECURSION, &map_clone::MAP_CLONE, &map_unit_fn::OPTION_MAP_UNIT_FN, @@ -1014,7 +1014,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(move || box excessive_bools::ExcessiveBools::new(max_struct_bools, max_fn_params_bools)); store.register_early_pass(|| box option_env_unwrap::OptionEnvUnwrap); store.register_late_pass(|| box wildcard_imports::WildcardImports); - store.register_early_pass(|| box macro_use::MacroUseImport); + store.register_early_pass(|| box macro_use::MacroUseImports); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1082,7 +1082,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&literal_representation::LARGE_DIGIT_GROUPS), LintId::of(&loops::EXPLICIT_INTO_ITER_LOOP), LintId::of(&loops::EXPLICIT_ITER_LOOP), - LintId::of(¯o_use::MACRO_USE_IMPORT), + LintId::of(¯o_use::MACRO_USE_IMPORTS), LintId::of(&matches::SINGLE_MATCH_ELSE), LintId::of(&methods::FILTER_MAP), LintId::of(&methods::FILTER_MAP_NEXT), diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index 43671d694131..b1345d0b751a 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -19,14 +19,14 @@ declare_clippy_lint! { /// #[macro_use] /// use lazy_static; /// ``` - pub MACRO_USE_IMPORT, + pub MACRO_USE_IMPORTS, pedantic, "#[macro_use] is no longer needed" } -declare_lint_pass!(MacroUseImport => [MACRO_USE_IMPORT]); +declare_lint_pass!(MacroUseImports => [MACRO_USE_IMPORTS]); -impl EarlyLintPass for MacroUseImport { +impl EarlyLintPass for MacroUseImports { fn check_item(&mut self, ecx: &EarlyContext<'_>, item: &ast::Item) { if_chain! { if ecx.sess.opts.edition == Edition::Edition2018; @@ -40,7 +40,7 @@ impl EarlyLintPass for MacroUseImport { let help = format!("use {}::", snippet(ecx, use_tree.span, "_")); span_lint_and_sugg( ecx, - MACRO_USE_IMPORT, + MACRO_USE_IMPORTS, mac_attr.span, msg, "remove the attribute and import the macro directly, try", diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 1635ff7babd7..4ae4ccc91f01 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1016,7 +1016,7 @@ pub const ALL_LINTS: [Lint; 360] = [ module: "float_literal", }, Lint { - name: "macro_use_import", + name: "macro_use_imports", group: "pedantic", desc: "#[macro_use] is no longer needed", deprecation: None, diff --git a/tests/ui/macro_use_import.rs b/tests/ui/macro_use_imports.rs similarity index 82% rename from tests/ui/macro_use_import.rs rename to tests/ui/macro_use_imports.rs index 33ce2b524ef7..094dce17d4b6 100644 --- a/tests/ui/macro_use_import.rs +++ b/tests/ui/macro_use_imports.rs @@ -1,5 +1,5 @@ // compile-flags: --edition 2018 -#![warn(clippy::macro_use_import)] +#![warn(clippy::macro_use_imports)] use std::collections::HashMap; #[macro_use] diff --git a/tests/ui/macro_use_import.stderr b/tests/ui/macro_use_imports.stderr similarity index 71% rename from tests/ui/macro_use_import.stderr rename to tests/ui/macro_use_imports.stderr index 1d86ba584411..b5e3dbec5727 100644 --- a/tests/ui/macro_use_import.stderr +++ b/tests/ui/macro_use_imports.stderr @@ -1,10 +1,10 @@ error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_import.rs:5:1 + --> $DIR/macro_use_imports.rs:5:1 | LL | #[macro_use] | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use std::prelude::` | - = note: `-D clippy::macro-use-import` implied by `-D warnings` + = note: `-D clippy::macro-use-imports` implied by `-D warnings` error: aborting due to previous error From d8167128fca35ce1ae645ef9a26fb3cece937c74 Mon Sep 17 00:00:00 2001 From: Chris Simpkins Date: Thu, 5 Mar 2020 23:32:04 -0500 Subject: [PATCH 183/243] transition rustc-guide to rustc-dev-guide --- doc/adding_lints.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/adding_lints.md b/doc/adding_lints.md index 7e1263ebf22f..1e78b0801d88 100644 --- a/doc/adding_lints.md +++ b/doc/adding_lints.md @@ -419,7 +419,7 @@ Here are some pointers to things you are likely going to need for every lint: * [`from_expansion`][from_expansion] and [`in_external_macro`][in_external_macro] * [`Span`][span] * [`Applicability`][applicability] -* [The rustc guide][rustc_guide] explains a lot of internal compiler concepts +* [The rustc-dev-guide][rustc-dev-guide] explains a lot of internal compiler concepts * [The nightly rustc docs][nightly_docs] which has been linked to throughout this guide @@ -459,5 +459,5 @@ don't hesitate to ask on Discord, IRC or in the issue/PR. [in_external_macro]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/fn.in_external_macro.html [play]: https://play.rust-lang.org [author_example]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=f093b986e80ad62f3b67a1f24f5e66e2 -[rustc_guide]: https://rust-lang.github.io/rustc-guide/ +[rustc-dev-guide]: https://rust-lang.github.io/rustc-dev-guide/ [nightly_docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ From 0f7f30711e4eb2f5f84fe198f325e512e404ee0c Mon Sep 17 00:00:00 2001 From: Jacob Meyers Date: Wed, 4 Mar 2020 21:13:57 -0500 Subject: [PATCH 184/243] add lint on File::read_to_string and File::read_to_end --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 5 ++ clippy_lints/src/utils/paths.rs | 1 + clippy_lints/src/verbose_file_reads.rs | 82 ++++++++++++++++++++++++++ src/lintlist/mod.rs | 9 ++- tests/ui/verbose_file_reads.rs | 30 ++++++++++ tests/ui/verbose_file_reads.stderr | 19 ++++++ 8 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 clippy_lints/src/verbose_file_reads.rs create mode 100644 tests/ui/verbose_file_reads.rs create mode 100644 tests/ui/verbose_file_reads.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index c3f291bc046d..32cbbe801017 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1417,6 +1417,7 @@ Released 2018-09-13 [`useless_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec [`vec_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#vec_box [`verbose_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask +[`verbose_file_reads`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_file_reads [`while_immutable_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_immutable_condition [`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop [`while_let_on_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator diff --git a/README.md b/README.md index 8635b2b6d5a5..2181c296e9b2 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 360 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 361 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 02c016c385dd..1eac69678a64 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -310,6 +310,7 @@ pub mod unused_self; pub mod unwrap; pub mod use_self; pub mod vec; +pub mod verbose_file_reads; pub mod wildcard_dependencies; pub mod wildcard_imports; pub mod write; @@ -815,6 +816,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &unwrap::UNNECESSARY_UNWRAP, &use_self::USE_SELF, &vec::USELESS_VEC, + &verbose_file_reads::VERBOSE_FILE_READS, &wildcard_dependencies::WILDCARD_DEPENDENCIES, &wildcard_imports::ENUM_GLOB_USE, &wildcard_imports::WILDCARD_IMPORTS, @@ -1015,6 +1017,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| box option_env_unwrap::OptionEnvUnwrap); store.register_late_pass(|| box wildcard_imports::WildcardImports); store.register_early_pass(|| box macro_use::MacroUseImports); + store.register_late_pass(|| box verbose_file_reads::VerboseFileReads); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1372,6 +1375,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&unwrap::PANICKING_UNWRAP), LintId::of(&unwrap::UNNECESSARY_UNWRAP), LintId::of(&vec::USELESS_VEC), + LintId::of(&verbose_file_reads::VERBOSE_FILE_READS), LintId::of(&write::PRINTLN_EMPTY_STRING), LintId::of(&write::PRINT_LITERAL), LintId::of(&write::PRINT_WITH_NEWLINE), @@ -1555,6 +1559,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&types::UNNECESSARY_CAST), LintId::of(&types::VEC_BOX), LintId::of(&unwrap::UNNECESSARY_UNWRAP), + LintId::of(&verbose_file_reads::VERBOSE_FILE_READS), LintId::of(&zero_div_zero::ZERO_DIVIDED_BY_ZERO), ]); diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 5ec04d965c86..6cb1f694fd5e 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -31,6 +31,7 @@ pub const DROP_TRAIT: [&str; 4] = ["core", "ops", "drop", "Drop"]; pub const DURATION: [&str; 3] = ["core", "time", "Duration"]; pub const EARLY_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "EarlyContext"]; pub const EXIT: [&str; 3] = ["std", "process", "exit"]; +pub const FILE: [&str; 3] = ["std", "fs", "File"]; pub const FILE_TYPE: [&str; 3] = ["std", "fs", "FileType"]; pub const FMT_ARGUMENTS_NEW_V1: [&str; 4] = ["core", "fmt", "Arguments", "new_v1"]; pub const FMT_ARGUMENTS_NEW_V1_FORMATTED: [&str; 4] = ["core", "fmt", "Arguments", "new_v1_formatted"]; diff --git a/clippy_lints/src/verbose_file_reads.rs b/clippy_lints/src/verbose_file_reads.rs new file mode 100644 index 000000000000..93256790211a --- /dev/null +++ b/clippy_lints/src/verbose_file_reads.rs @@ -0,0 +1,82 @@ +use crate::utils::{match_type, paths, span_lint_and_help}; +use if_chain::if_chain; +use rustc_hir::{Expr, ExprKind, QPath}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// **What it does:** Checks for use of File::read_to_end and File::read_to_string. + /// + /// **Why is this bad?** `fs::{read, read_to_string}` provide the same functionality when `buf` is empty with fewer imports and no intermediate values. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust, ignore + /// let mut f = File::open("foo.txt")?; + /// let mut bytes = Vec::new(); + /// f.read_to_end(&mut bytes)?; + /// ``` + /// Can be written more concisely as + /// ```rust, ignore + /// let mut bytes = fs::read("foo.txt")?; + /// ``` + pub VERBOSE_FILE_READS, + complexity, + "use of `File::read_to_end` or `File::read_to_string`" +} + +declare_lint_pass!(VerboseFileReads => [VERBOSE_FILE_READS]); + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VerboseFileReads { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) { + if is_file_read_to_end(cx, expr) { + span_lint_and_help( + cx, + VERBOSE_FILE_READS, + expr.span, + "use of File::read_to_end", + "consider using fs::read instead", + ); + } else if is_file_read_to_string(cx, expr) { + span_lint_and_help( + cx, + VERBOSE_FILE_READS, + expr.span, + "use of File::read_to_string", + "consider using fs::read_to_string instead", + ) + } else { + // Don't care + } + } +} + +fn is_file_read_to_end<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) -> bool { + if_chain! { + if let ExprKind::MethodCall(method_name, _, exprs) = expr.kind; + if method_name.ident.as_str() == "read_to_end"; + if let ExprKind::Path(QPath::Resolved(None, _)) = &exprs[0].kind; + let ty = cx.tables.expr_ty(&exprs[0]); + if match_type(cx, ty, &paths::FILE); + then { + return true + } + } + false +} + +fn is_file_read_to_string<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) -> bool { + if_chain! { + if let ExprKind::MethodCall(method_name, _, exprs) = expr.kind; + if method_name.ident.as_str() == "read_to_string"; + if let ExprKind::Path(QPath::Resolved(None, _)) = &exprs[0].kind; + let ty = cx.tables.expr_ty(&exprs[0]); + if match_type(cx, ty, &paths::FILE); + then { + return true + } + } + false +} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 4ae4ccc91f01..fd948953ea23 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -6,7 +6,7 @@ pub use lint::Lint; pub use lint::LINT_LEVELS; // begin lint list, do not remove this comment, it’s used in `update_lints` -pub const ALL_LINTS: [Lint; 360] = [ +pub const ALL_LINTS: [Lint; 361] = [ Lint { name: "absurd_extreme_comparisons", group: "correctness", @@ -2401,6 +2401,13 @@ pub const ALL_LINTS: [Lint; 360] = [ deprecation: None, module: "bit_mask", }, + Lint { + name: "verbose_file_reads", + group: "complexity", + desc: "use of `File::read_to_end` or `File::read_to_string`", + deprecation: None, + module: "verbose_file_reads", + }, Lint { name: "while_immutable_condition", group: "correctness", diff --git a/tests/ui/verbose_file_reads.rs b/tests/ui/verbose_file_reads.rs new file mode 100644 index 000000000000..3c7c4be84b0c --- /dev/null +++ b/tests/ui/verbose_file_reads.rs @@ -0,0 +1,30 @@ +#![warn(clippy::verbose_file_reads)] +use std::env::temp_dir; +use std::fs::File; +use std::io::Read; + +struct Struct; +// To make sure we only warn on File::{read_to_end, read_to_string} calls +impl Struct { + pub fn read_to_end(&self) {} + + pub fn read_to_string(&self) {} +} + +fn main() -> std::io::Result<()> { + let mut path = temp_dir(); + path.push("test.txt"); + let file = File::create(&path)?; + // Lint shouldn't catch this + let s = Struct; + s.read_to_end(); + s.read_to_string(); + // Should catch this + let mut f = File::open(&path)?; + let mut buffer = Vec::new(); + f.read_to_end(&mut buffer)?; + // ...and this + let mut string_buffer = String::new(); + f.read_to_string(&mut string_buffer)?; + Ok(()) +} diff --git a/tests/ui/verbose_file_reads.stderr b/tests/ui/verbose_file_reads.stderr new file mode 100644 index 000000000000..73dc22fd4dbc --- /dev/null +++ b/tests/ui/verbose_file_reads.stderr @@ -0,0 +1,19 @@ +error: use of File::read_to_end + --> $DIR/verbose_file_reads.rs:25:5 + | +LL | f.read_to_end(&mut buffer)?; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::verbose-file-reads` implied by `-D warnings` + = help: consider using fs::read instead + +error: use of File::read_to_string + --> $DIR/verbose_file_reads.rs:28:5 + | +LL | f.read_to_string(&mut string_buffer)?; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using fs::read_to_string instead + +error: aborting due to 2 previous errors + From 806699342e5dcfaa031aadd0fe5649fdaee33afe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 8 Mar 2020 01:33:17 +0100 Subject: [PATCH 185/243] deps: bump itertools 0.8 -> 0.9 changelog: none --- clippy_lints/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index ad3b077ec4b9..99eebcdd3d59 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -19,7 +19,7 @@ edition = "2018" [dependencies] cargo_metadata = "0.9.0" if_chain = "1.0.0" -itertools = "0.8" +itertools = "0.9" lazy_static = "1.0.2" matches = "0.1.7" pulldown-cmark = { version = "0.7", default-features = false } From a412b3423e99c2cf0841ffc2f406322b1b0c9c29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 8 Mar 2020 02:50:33 +0100 Subject: [PATCH 186/243] check_pat: delay creation of the "normal" vec until we reach the branch where is is actually needed --- clippy_lints/src/misc_early.rs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 60b672766231..28fdb3d015ed 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -318,18 +318,6 @@ impl EarlyLintPass for MiscEarlyLints { return; } if wilds > 0 { - let mut normal = vec![]; - - for field in pfields { - match field.pat.kind { - PatKind::Wild => {}, - _ => { - if let Ok(n) = cx.sess().source_map().span_to_snippet(field.span) { - normal.push(n); - } - }, - } - } for field in pfields { if let PatKind::Wild = field.pat.kind { wilds -= 1; @@ -341,6 +329,19 @@ impl EarlyLintPass for MiscEarlyLints { "You matched a field with a wildcard pattern. Consider using `..` instead", ); } else { + let mut normal = vec![]; + + for field in pfields { + match field.pat.kind { + PatKind::Wild => {}, + _ => { + if let Ok(n) = cx.sess().source_map().span_to_snippet(field.span) { + normal.push(n); + } + }, + } + } + span_lint_and_help( cx, UNNEEDED_FIELD_PATTERN, From 75a2300e27a8402744ce122610f42c30d4890bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 8 Mar 2020 10:00:23 +0100 Subject: [PATCH 187/243] redundant_pattern: take binding (ref, ref mut) into account in suggestion. fixes #5271 --- clippy_lints/src/misc_early.rs | 14 ++++++++++---- tests/ui/patterns.fixed | 16 ++++++++++++++++ tests/ui/patterns.rs | 16 ++++++++++++++++ tests/ui/patterns.stderr | 14 +++++++++++++- 4 files changed, 55 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 60b672766231..28bcc3f841af 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -5,8 +5,8 @@ use crate::utils::{ use if_chain::if_chain; use rustc::lint::in_external_macro; use rustc_ast::ast::{ - Block, Expr, ExprKind, GenericParamKind, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind, - StmtKind, UnOp, + BindingMode, Block, Expr, ExprKind, GenericParamKind, Generics, Lit, LitFloatType, LitIntType, LitKind, Mutability, + NodeId, Pat, PatKind, StmtKind, UnOp, }; use rustc_ast::visit::{walk_expr, FnKind, Visitor}; use rustc_data_structures::fx::FxHashMap; @@ -355,7 +355,13 @@ impl EarlyLintPass for MiscEarlyLints { } } - if let PatKind::Ident(_, ident, Some(ref right)) = pat.kind { + if let PatKind::Ident(left, ident, Some(ref right)) = pat.kind { + let left_binding = match left { + BindingMode::ByRef(Mutability::Mut) => "ref mut ", + BindingMode::ByRef(Mutability::Not) => "ref ", + _ => "", + }; + if let PatKind::Wild = right.kind { span_lint_and_sugg( cx, @@ -366,7 +372,7 @@ impl EarlyLintPass for MiscEarlyLints { ident.name, ident.name, ), "try", - format!("{}", ident.name), + format!("{}{}", left_binding, ident.name), Applicability::MachineApplicable, ); } diff --git a/tests/ui/patterns.fixed b/tests/ui/patterns.fixed index dfe27e193b97..f22388154499 100644 --- a/tests/ui/patterns.fixed +++ b/tests/ui/patterns.fixed @@ -17,4 +17,20 @@ fn main() { [x, inside @ .., y] => (), // no error [..] => (), } + + let mut mutv = vec![1, 2, 3]; + + // required "ref" left out in suggestion: #5271 + match mutv { + ref mut x => { + x.push(4); + println!("vec: {:?}", x); + }, + ref y if y == &vec![0] => (), + } + + match mutv { + ref x => println!("vec: {:?}", x), + ref y if y == &vec![0] => (), + } } diff --git a/tests/ui/patterns.rs b/tests/ui/patterns.rs index bd202fc04205..5848ecd38d98 100644 --- a/tests/ui/patterns.rs +++ b/tests/ui/patterns.rs @@ -17,4 +17,20 @@ fn main() { [x, inside @ .., y] => (), // no error [..] => (), } + + let mut mutv = vec![1, 2, 3]; + + // required "ref" left out in suggestion: #5271 + match mutv { + ref mut x @ _ => { + x.push(4); + println!("vec: {:?}", x); + }, + ref y if y == &vec![0] => (), + } + + match mutv { + ref x @ _ => println!("vec: {:?}", x), + ref y if y == &vec![0] => (), + } } diff --git a/tests/ui/patterns.stderr b/tests/ui/patterns.stderr index f25e71e872b2..af067580688b 100644 --- a/tests/ui/patterns.stderr +++ b/tests/ui/patterns.stderr @@ -6,5 +6,17 @@ LL | y @ _ => (), | = note: `-D clippy::redundant-pattern` implied by `-D warnings` -error: aborting due to previous error +error: the `x @ _` pattern can be written as just `x` + --> $DIR/patterns.rs:25:9 + | +LL | ref mut x @ _ => { + | ^^^^^^^^^^^^^ help: try: `ref mut x` + +error: the `x @ _` pattern can be written as just `x` + --> $DIR/patterns.rs:33:9 + | +LL | ref x @ _ => println!("vec: {:?}", x), + | ^^^^^^^^^ help: try: `ref x` + +error: aborting due to 3 previous errors From 3b3e5ea2a22694159072c682ca88a9407540710b Mon Sep 17 00:00:00 2001 From: Vivek Ghaisas Date: Sun, 8 Mar 2020 20:57:42 +0000 Subject: [PATCH 188/243] Mention the setup instructions in CONTRIBUTING Multiple people seem to have missed this based on questions asked in the Discord channel. Might as well mention it up front. --- CONTRIBUTING.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4777f2fabeb2..3fc9b14e8a73 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,8 +28,9 @@ High level approach: 1. Find something to fix/improve 2. Change code (likely some file in `clippy_lints/src/`) -3. Run `cargo test` in the root directory and wiggle code until it passes -4. Open a PR (also can be done between 2. and 3. if you run into problems) +3. Follow the instructions in the [docs for writing lints](doc/adding_lints.md) such as running the `setup-toolchain.sh` script +4. Run `cargo test` in the root directory and wiggle code until it passes +5. Open a PR (also can be done after 2. if you run into problems) ### Finding something to fix/improve From ab6e709ee66025358ee91175f98804df7ec4f625 Mon Sep 17 00:00:00 2001 From: Vivek Ghaisas Date: Sun, 8 Mar 2020 21:28:06 +0000 Subject: [PATCH 189/243] Improve error messages for {option,result}_map_unit_fn Instead of saying "unit function", use the phrase the description uses: "function that returns the unit type". Fixes #5180. --- clippy_lints/src/map_unit_fn.rs | 2 +- tests/ui/option_map_unit_fn_fixable.stderr | 34 +++++++++++----------- tests/ui/result_map_unit_fn_fixable.stderr | 34 +++++++++++----------- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 8bc08c342dc9..a4e1b2c0d332 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -198,7 +198,7 @@ fn let_binding_name(cx: &LateContext<'_, '_>, var_arg: &hir::Expr<'_>) -> String #[must_use] fn suggestion_msg(function_type: &str, map_type: &str) -> String { format!( - "called `map(f)` on an `{0}` value where `f` is a unit {1}", + "called `map(f)` on an `{0}` value where `f` is a {1} that returns the unit type", map_type, function_type ) } diff --git a/tests/ui/option_map_unit_fn_fixable.stderr b/tests/ui/option_map_unit_fn_fixable.stderr index f993e1931d59..f84d1fadf7f3 100644 --- a/tests/ui/option_map_unit_fn_fixable.stderr +++ b/tests/ui/option_map_unit_fn_fixable.stderr @@ -1,4 +1,4 @@ -error: called `map(f)` on an `Option` value where `f` is a unit function +error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type --> $DIR/option_map_unit_fn_fixable.rs:34:5 | LL | x.field.map(do_nothing); @@ -8,7 +8,7 @@ LL | x.field.map(do_nothing); | = note: `-D clippy::option-map-unit-fn` implied by `-D warnings` -error: called `map(f)` on an `Option` value where `f` is a unit function +error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type --> $DIR/option_map_unit_fn_fixable.rs:36:5 | LL | x.field.map(do_nothing); @@ -16,7 +16,7 @@ LL | x.field.map(do_nothing); | | | help: try this: `if let Some(x_field) = x.field { do_nothing(x_field) }` -error: called `map(f)` on an `Option` value where `f` is a unit function +error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type --> $DIR/option_map_unit_fn_fixable.rs:38:5 | LL | x.field.map(diverge); @@ -24,7 +24,7 @@ LL | x.field.map(diverge); | | | help: try this: `if let Some(x_field) = x.field { diverge(x_field) }` -error: called `map(f)` on an `Option` value where `f` is a unit closure +error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type --> $DIR/option_map_unit_fn_fixable.rs:44:5 | LL | x.field.map(|value| x.do_option_nothing(value + captured)); @@ -32,7 +32,7 @@ LL | x.field.map(|value| x.do_option_nothing(value + captured)); | | | help: try this: `if let Some(value) = x.field { x.do_option_nothing(value + captured) }` -error: called `map(f)` on an `Option` value where `f` is a unit closure +error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type --> $DIR/option_map_unit_fn_fixable.rs:46:5 | LL | x.field.map(|value| { x.do_option_plus_one(value + captured); }); @@ -40,7 +40,7 @@ LL | x.field.map(|value| { x.do_option_plus_one(value + captured); }); | | | help: try this: `if let Some(value) = x.field { x.do_option_plus_one(value + captured); }` -error: called `map(f)` on an `Option` value where `f` is a unit closure +error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type --> $DIR/option_map_unit_fn_fixable.rs:49:5 | LL | x.field.map(|value| do_nothing(value + captured)); @@ -48,7 +48,7 @@ LL | x.field.map(|value| do_nothing(value + captured)); | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` -error: called `map(f)` on an `Option` value where `f` is a unit closure +error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type --> $DIR/option_map_unit_fn_fixable.rs:51:5 | LL | x.field.map(|value| { do_nothing(value + captured) }); @@ -56,7 +56,7 @@ LL | x.field.map(|value| { do_nothing(value + captured) }); | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` -error: called `map(f)` on an `Option` value where `f` is a unit closure +error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type --> $DIR/option_map_unit_fn_fixable.rs:53:5 | LL | x.field.map(|value| { do_nothing(value + captured); }); @@ -64,7 +64,7 @@ LL | x.field.map(|value| { do_nothing(value + captured); }); | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` -error: called `map(f)` on an `Option` value where `f` is a unit closure +error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type --> $DIR/option_map_unit_fn_fixable.rs:55:5 | LL | x.field.map(|value| { { do_nothing(value + captured); } }); @@ -72,7 +72,7 @@ LL | x.field.map(|value| { { do_nothing(value + captured); } }); | | | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` -error: called `map(f)` on an `Option` value where `f` is a unit closure +error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type --> $DIR/option_map_unit_fn_fixable.rs:58:5 | LL | x.field.map(|value| diverge(value + captured)); @@ -80,7 +80,7 @@ LL | x.field.map(|value| diverge(value + captured)); | | | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` -error: called `map(f)` on an `Option` value where `f` is a unit closure +error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type --> $DIR/option_map_unit_fn_fixable.rs:60:5 | LL | x.field.map(|value| { diverge(value + captured) }); @@ -88,7 +88,7 @@ LL | x.field.map(|value| { diverge(value + captured) }); | | | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` -error: called `map(f)` on an `Option` value where `f` is a unit closure +error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type --> $DIR/option_map_unit_fn_fixable.rs:62:5 | LL | x.field.map(|value| { diverge(value + captured); }); @@ -96,7 +96,7 @@ LL | x.field.map(|value| { diverge(value + captured); }); | | | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` -error: called `map(f)` on an `Option` value where `f` is a unit closure +error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type --> $DIR/option_map_unit_fn_fixable.rs:64:5 | LL | x.field.map(|value| { { diverge(value + captured); } }); @@ -104,7 +104,7 @@ LL | x.field.map(|value| { { diverge(value + captured); } }); | | | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` -error: called `map(f)` on an `Option` value where `f` is a unit closure +error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type --> $DIR/option_map_unit_fn_fixable.rs:69:5 | LL | x.field.map(|value| { let y = plus_one(value + captured); }); @@ -112,7 +112,7 @@ LL | x.field.map(|value| { let y = plus_one(value + captured); }); | | | help: try this: `if let Some(value) = x.field { let y = plus_one(value + captured); }` -error: called `map(f)` on an `Option` value where `f` is a unit closure +error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type --> $DIR/option_map_unit_fn_fixable.rs:71:5 | LL | x.field.map(|value| { plus_one(value + captured); }); @@ -120,7 +120,7 @@ LL | x.field.map(|value| { plus_one(value + captured); }); | | | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` -error: called `map(f)` on an `Option` value where `f` is a unit closure +error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type --> $DIR/option_map_unit_fn_fixable.rs:73:5 | LL | x.field.map(|value| { { plus_one(value + captured); } }); @@ -128,7 +128,7 @@ LL | x.field.map(|value| { { plus_one(value + captured); } }); | | | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` -error: called `map(f)` on an `Option` value where `f` is a unit closure +error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type --> $DIR/option_map_unit_fn_fixable.rs:76:5 | LL | x.field.map(|ref value| { do_nothing(value + captured) });} diff --git a/tests/ui/result_map_unit_fn_fixable.stderr b/tests/ui/result_map_unit_fn_fixable.stderr index 33be39e34f15..467e00263cd3 100644 --- a/tests/ui/result_map_unit_fn_fixable.stderr +++ b/tests/ui/result_map_unit_fn_fixable.stderr @@ -1,4 +1,4 @@ -error: called `map(f)` on an `Result` value where `f` is a unit function +error: called `map(f)` on an `Result` value where `f` is a function that returns the unit type --> $DIR/result_map_unit_fn_fixable.rs:35:5 | LL | x.field.map(do_nothing); @@ -8,7 +8,7 @@ LL | x.field.map(do_nothing); | = note: `-D clippy::result-map-unit-fn` implied by `-D warnings` -error: called `map(f)` on an `Result` value where `f` is a unit function +error: called `map(f)` on an `Result` value where `f` is a function that returns the unit type --> $DIR/result_map_unit_fn_fixable.rs:37:5 | LL | x.field.map(do_nothing); @@ -16,7 +16,7 @@ LL | x.field.map(do_nothing); | | | help: try this: `if let Ok(x_field) = x.field { do_nothing(x_field) }` -error: called `map(f)` on an `Result` value where `f` is a unit function +error: called `map(f)` on an `Result` value where `f` is a function that returns the unit type --> $DIR/result_map_unit_fn_fixable.rs:39:5 | LL | x.field.map(diverge); @@ -24,7 +24,7 @@ LL | x.field.map(diverge); | | | help: try this: `if let Ok(x_field) = x.field { diverge(x_field) }` -error: called `map(f)` on an `Result` value where `f` is a unit closure +error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type --> $DIR/result_map_unit_fn_fixable.rs:45:5 | LL | x.field.map(|value| x.do_result_nothing(value + captured)); @@ -32,7 +32,7 @@ LL | x.field.map(|value| x.do_result_nothing(value + captured)); | | | help: try this: `if let Ok(value) = x.field { x.do_result_nothing(value + captured) }` -error: called `map(f)` on an `Result` value where `f` is a unit closure +error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type --> $DIR/result_map_unit_fn_fixable.rs:47:5 | LL | x.field.map(|value| { x.do_result_plus_one(value + captured); }); @@ -40,7 +40,7 @@ LL | x.field.map(|value| { x.do_result_plus_one(value + captured); }); | | | help: try this: `if let Ok(value) = x.field { x.do_result_plus_one(value + captured); }` -error: called `map(f)` on an `Result` value where `f` is a unit closure +error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type --> $DIR/result_map_unit_fn_fixable.rs:50:5 | LL | x.field.map(|value| do_nothing(value + captured)); @@ -48,7 +48,7 @@ LL | x.field.map(|value| do_nothing(value + captured)); | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` -error: called `map(f)` on an `Result` value where `f` is a unit closure +error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type --> $DIR/result_map_unit_fn_fixable.rs:52:5 | LL | x.field.map(|value| { do_nothing(value + captured) }); @@ -56,7 +56,7 @@ LL | x.field.map(|value| { do_nothing(value + captured) }); | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` -error: called `map(f)` on an `Result` value where `f` is a unit closure +error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type --> $DIR/result_map_unit_fn_fixable.rs:54:5 | LL | x.field.map(|value| { do_nothing(value + captured); }); @@ -64,7 +64,7 @@ LL | x.field.map(|value| { do_nothing(value + captured); }); | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` -error: called `map(f)` on an `Result` value where `f` is a unit closure +error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type --> $DIR/result_map_unit_fn_fixable.rs:56:5 | LL | x.field.map(|value| { { do_nothing(value + captured); } }); @@ -72,7 +72,7 @@ LL | x.field.map(|value| { { do_nothing(value + captured); } }); | | | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` -error: called `map(f)` on an `Result` value where `f` is a unit closure +error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type --> $DIR/result_map_unit_fn_fixable.rs:59:5 | LL | x.field.map(|value| diverge(value + captured)); @@ -80,7 +80,7 @@ LL | x.field.map(|value| diverge(value + captured)); | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` -error: called `map(f)` on an `Result` value where `f` is a unit closure +error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type --> $DIR/result_map_unit_fn_fixable.rs:61:5 | LL | x.field.map(|value| { diverge(value + captured) }); @@ -88,7 +88,7 @@ LL | x.field.map(|value| { diverge(value + captured) }); | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` -error: called `map(f)` on an `Result` value where `f` is a unit closure +error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type --> $DIR/result_map_unit_fn_fixable.rs:63:5 | LL | x.field.map(|value| { diverge(value + captured); }); @@ -96,7 +96,7 @@ LL | x.field.map(|value| { diverge(value + captured); }); | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` -error: called `map(f)` on an `Result` value where `f` is a unit closure +error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type --> $DIR/result_map_unit_fn_fixable.rs:65:5 | LL | x.field.map(|value| { { diverge(value + captured); } }); @@ -104,7 +104,7 @@ LL | x.field.map(|value| { { diverge(value + captured); } }); | | | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` -error: called `map(f)` on an `Result` value where `f` is a unit closure +error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type --> $DIR/result_map_unit_fn_fixable.rs:70:5 | LL | x.field.map(|value| { let y = plus_one(value + captured); }); @@ -112,7 +112,7 @@ LL | x.field.map(|value| { let y = plus_one(value + captured); }); | | | help: try this: `if let Ok(value) = x.field { let y = plus_one(value + captured); }` -error: called `map(f)` on an `Result` value where `f` is a unit closure +error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type --> $DIR/result_map_unit_fn_fixable.rs:72:5 | LL | x.field.map(|value| { plus_one(value + captured); }); @@ -120,7 +120,7 @@ LL | x.field.map(|value| { plus_one(value + captured); }); | | | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` -error: called `map(f)` on an `Result` value where `f` is a unit closure +error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type --> $DIR/result_map_unit_fn_fixable.rs:74:5 | LL | x.field.map(|value| { { plus_one(value + captured); } }); @@ -128,7 +128,7 @@ LL | x.field.map(|value| { { plus_one(value + captured); } }); | | | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` -error: called `map(f)` on an `Result` value where `f` is a unit closure +error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type --> $DIR/result_map_unit_fn_fixable.rs:77:5 | LL | x.field.map(|ref value| { do_nothing(value + captured) }); From 40a04f26572cf69c74c8790830a49d6a1d16c3fb Mon Sep 17 00:00:00 2001 From: ThibsG Date: Sun, 8 Mar 2020 22:57:35 +0100 Subject: [PATCH 190/243] Fix match single binding when in a let stmt --- clippy_lints/src/matches.rs | 54 ++++++++++++++++++++++------ tests/ui/match_single_binding.fixed | 9 ++++- tests/ui/match_single_binding.rs | 10 +++++- tests/ui/match_single_binding.stderr | 34 ++++++++++++------ 4 files changed, 84 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 9668c5d83499..b0aae5e30e6e 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -14,8 +14,8 @@ use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::def::CtorKind; use rustc_hir::{ - print, Arm, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, Local, MatchSource, Mutability, Pat, PatKind, - QPath, RangeEnd, + print, Arm, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, Local, MatchSource, Mutability, Node, Pat, + PatKind, QPath, RangeEnd, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -882,7 +882,7 @@ fn check_wild_in_or_pats(cx: &LateContext<'_, '_>, arms: &[Arm<'_>]) { } } -fn check_match_single_binding(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) { +fn check_match_single_binding<'a>(cx: &LateContext<'_, 'a>, ex: &Expr<'a>, arms: &[Arm<'_>], expr: &Expr<'_>) { if in_macro(expr.span) || arms.len() != 1 || is_refutable(cx, arms[0].pat) { return; } @@ -914,19 +914,38 @@ fn check_match_single_binding(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[A let mut applicability = Applicability::MaybeIncorrect; match arms[0].pat.kind { PatKind::Binding(..) | PatKind::Tuple(_, _) | PatKind::Struct(..) => { + // If this match is in a local (`let`) stmt + let (target_span, sugg) = if let Some(parent_let_node) = opt_parent_let(cx, ex) { + ( + parent_let_node.span, + format!( + "let {} = {};\n{}let {} = {};", + snippet_with_applicability(cx, bind_names, "..", &mut applicability), + snippet_with_applicability(cx, matched_vars, "..", &mut applicability), + " ".repeat(indent_of(cx, expr.span).unwrap_or(0)), + snippet_with_applicability(cx, parent_let_node.pat.span, "..", &mut applicability), + snippet_body + ), + ) + } else { + ( + expr.span, + format!( + "let {} = {};\n{}{}", + snippet_with_applicability(cx, bind_names, "..", &mut applicability), + snippet_with_applicability(cx, matched_vars, "..", &mut applicability), + " ".repeat(indent_of(cx, expr.span).unwrap_or(0)), + snippet_body + ), + ) + }; span_lint_and_sugg( cx, MATCH_SINGLE_BINDING, - expr.span, + target_span, "this match could be written as a `let` statement", "consider using `let` statement", - format!( - "let {} = {};\n{}{}", - snippet_with_applicability(cx, bind_names, "..", &mut applicability), - snippet_with_applicability(cx, matched_vars, "..", &mut applicability), - " ".repeat(indent_of(cx, expr.span).unwrap_or(0)), - snippet_body, - ), + sugg, applicability, ); }, @@ -945,6 +964,19 @@ fn check_match_single_binding(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[A } } +/// Returns true if the `ex` match expression is in a local (`let`) statement +fn opt_parent_let<'a>(cx: &LateContext<'_, 'a>, ex: &Expr<'a>) -> Option<&'a Local<'a>> { + if_chain! { + let map = &cx.tcx.hir(); + if let Some(Node::Expr(parent_arm_expr)) = map.find(map.get_parent_node(ex.hir_id)); + if let Some(Node::Local(parent_let_expr)) = map.find(map.get_parent_node(parent_arm_expr.hir_id)); + then { + return Some(parent_let_expr); + } + } + None +} + /// Gets all arms that are unbounded `PatRange`s. fn all_ranges<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, diff --git a/tests/ui/match_single_binding.fixed b/tests/ui/match_single_binding.fixed index 932bd6783a15..bc2346a8dbf0 100644 --- a/tests/ui/match_single_binding.fixed +++ b/tests/ui/match_single_binding.fixed @@ -1,13 +1,17 @@ // run-rustfix #![warn(clippy::match_single_binding)] -#![allow(clippy::many_single_char_names, clippy::toplevel_ref_arg)] +#![allow(unused_variables, clippy::many_single_char_names, clippy::toplevel_ref_arg)] struct Point { x: i32, y: i32, } +fn coords() -> Point { + Point { x: 1, y: 2 } +} + fn main() { let a = 1; let b = 2; @@ -60,4 +64,7 @@ fn main() { let mut x = 5; let ref mut mr = x; println!("Got a mutable reference to {}", mr); + // Lint + let Point { x, y } = coords(); + let product = x * y; } diff --git a/tests/ui/match_single_binding.rs b/tests/ui/match_single_binding.rs index 55b0b09a0088..0517b3bbfbf9 100644 --- a/tests/ui/match_single_binding.rs +++ b/tests/ui/match_single_binding.rs @@ -1,13 +1,17 @@ // run-rustfix #![warn(clippy::match_single_binding)] -#![allow(clippy::many_single_char_names, clippy::toplevel_ref_arg)] +#![allow(unused_variables, clippy::many_single_char_names, clippy::toplevel_ref_arg)] struct Point { x: i32, y: i32, } +fn coords() -> Point { + Point { x: 1, y: 2 } +} + fn main() { let a = 1; let b = 2; @@ -72,4 +76,8 @@ fn main() { match x { ref mut mr => println!("Got a mutable reference to {}", mr), } + // Lint + let product = match coords() { + Point { x, y } => x * y, + }; } diff --git a/tests/ui/match_single_binding.stderr b/tests/ui/match_single_binding.stderr index 471aec780d23..05ba9e5f7f3c 100644 --- a/tests/ui/match_single_binding.stderr +++ b/tests/ui/match_single_binding.stderr @@ -1,5 +1,5 @@ error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:16:5 + --> $DIR/match_single_binding.rs:20:5 | LL | / match (a, b, c) { LL | | (x, y, z) => { @@ -18,7 +18,7 @@ LL | } | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:22:5 + --> $DIR/match_single_binding.rs:26:5 | LL | / match (a, b, c) { LL | | (x, y, z) => println!("{} {} {}", x, y, z), @@ -32,7 +32,7 @@ LL | println!("{} {} {}", x, y, z); | error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:37:5 + --> $DIR/match_single_binding.rs:41:5 | LL | / match a { LL | | _ => println!("whatever"), @@ -40,7 +40,7 @@ LL | | } | |_____^ help: consider using the match body instead: `println!("whatever");` error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:41:5 + --> $DIR/match_single_binding.rs:45:5 | LL | / match a { LL | | _ => { @@ -59,7 +59,7 @@ LL | } | error: this match could be replaced by its body itself - --> $DIR/match_single_binding.rs:48:5 + --> $DIR/match_single_binding.rs:52:5 | LL | / match a { LL | | _ => { @@ -81,7 +81,7 @@ LL | } | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:58:5 + --> $DIR/match_single_binding.rs:62:5 | LL | / match p { LL | | Point { x, y } => println!("Coords: ({}, {})", x, y), @@ -95,7 +95,7 @@ LL | println!("Coords: ({}, {})", x, y); | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:62:5 + --> $DIR/match_single_binding.rs:66:5 | LL | / match p { LL | | Point { x: x1, y: y1 } => println!("Coords: ({}, {})", x1, y1), @@ -109,7 +109,7 @@ LL | println!("Coords: ({}, {})", x1, y1); | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:67:5 + --> $DIR/match_single_binding.rs:71:5 | LL | / match x { LL | | ref r => println!("Got a reference to {}", r), @@ -123,7 +123,7 @@ LL | println!("Got a reference to {}", r); | error: this match could be written as a `let` statement - --> $DIR/match_single_binding.rs:72:5 + --> $DIR/match_single_binding.rs:76:5 | LL | / match x { LL | | ref mut mr => println!("Got a mutable reference to {}", mr), @@ -136,5 +136,19 @@ LL | let ref mut mr = x; LL | println!("Got a mutable reference to {}", mr); | -error: aborting due to 9 previous errors +error: this match could be written as a `let` statement + --> $DIR/match_single_binding.rs:80:5 + | +LL | / let product = match coords() { +LL | | Point { x, y } => x * y, +LL | | }; + | |______^ + | +help: consider using `let` statement + | +LL | let Point { x, y } = coords(); +LL | let product = x * y; + | + +error: aborting due to 10 previous errors From 697e3c89a7a78d1615e714c3a83073c362e9aa3c Mon Sep 17 00:00:00 2001 From: Jacek Pospychala Date: Sun, 8 Mar 2020 23:43:40 +0100 Subject: [PATCH 191/243] Improve placeholder in map_unit_fn --- clippy_lints/src/map_unit_fn.rs | 4 +- tests/ui/option_map_unit_fn_fixable.fixed | 8 +++- tests/ui/option_map_unit_fn_fixable.rs | 8 +++- tests/ui/option_map_unit_fn_fixable.stderr | 46 +++++++++++++--------- 4 files changed, 43 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index a4e1b2c0d332..d7ea022d8886 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -186,12 +186,12 @@ fn unit_closure<'a, 'tcx>( /// `x.field` => `x_field` /// `y` => `_y` /// -/// Anything else will return `_`. +/// Anything else will return `a`. fn let_binding_name(cx: &LateContext<'_, '_>, var_arg: &hir::Expr<'_>) -> String { match &var_arg.kind { hir::ExprKind::Field(_, _) => snippet(cx, var_arg.span, "_").replace(".", "_"), hir::ExprKind::Path(_) => format!("_{}", snippet(cx, var_arg.span, "")), - _ => "_".to_string(), + _ => "a".to_string(), } } diff --git a/tests/ui/option_map_unit_fn_fixable.fixed b/tests/ui/option_map_unit_fn_fixable.fixed index ad153e4fc194..9a0da404cb6d 100644 --- a/tests/ui/option_map_unit_fn_fixable.fixed +++ b/tests/ui/option_map_unit_fn_fixable.fixed @@ -13,6 +13,10 @@ fn plus_one(value: usize) -> usize { value + 1 } +fn option() -> Option { + Some(10) +} + struct HasOption { field: Option, } @@ -73,6 +77,8 @@ fn option_map_unit_fn() { if let Some(value) = x.field { plus_one(value + captured); } - if let Some(ref value) = x.field { do_nothing(value + captured) }} + if let Some(ref value) = x.field { do_nothing(value + captured) } + + if let Some(a) = option() { do_nothing(a) }} fn main() {} diff --git a/tests/ui/option_map_unit_fn_fixable.rs b/tests/ui/option_map_unit_fn_fixable.rs index 6926498341ac..58041b62df35 100644 --- a/tests/ui/option_map_unit_fn_fixable.rs +++ b/tests/ui/option_map_unit_fn_fixable.rs @@ -13,6 +13,10 @@ fn plus_one(value: usize) -> usize { value + 1 } +fn option() -> Option { + Some(10) +} + struct HasOption { field: Option, } @@ -73,6 +77,8 @@ fn option_map_unit_fn() { x.field.map(|value| { { plus_one(value + captured); } }); - x.field.map(|ref value| { do_nothing(value + captured) });} + x.field.map(|ref value| { do_nothing(value + captured) }); + + option().map(do_nothing);} fn main() {} diff --git a/tests/ui/option_map_unit_fn_fixable.stderr b/tests/ui/option_map_unit_fn_fixable.stderr index f84d1fadf7f3..1312c70b6d59 100644 --- a/tests/ui/option_map_unit_fn_fixable.stderr +++ b/tests/ui/option_map_unit_fn_fixable.stderr @@ -1,5 +1,5 @@ error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type - --> $DIR/option_map_unit_fn_fixable.rs:34:5 + --> $DIR/option_map_unit_fn_fixable.rs:38:5 | LL | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- @@ -9,7 +9,7 @@ LL | x.field.map(do_nothing); = note: `-D clippy::option-map-unit-fn` implied by `-D warnings` error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type - --> $DIR/option_map_unit_fn_fixable.rs:36:5 + --> $DIR/option_map_unit_fn_fixable.rs:40:5 | LL | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- @@ -17,7 +17,7 @@ LL | x.field.map(do_nothing); | help: try this: `if let Some(x_field) = x.field { do_nothing(x_field) }` error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type - --> $DIR/option_map_unit_fn_fixable.rs:38:5 + --> $DIR/option_map_unit_fn_fixable.rs:42:5 | LL | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- @@ -25,7 +25,7 @@ LL | x.field.map(diverge); | help: try this: `if let Some(x_field) = x.field { diverge(x_field) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type - --> $DIR/option_map_unit_fn_fixable.rs:44:5 + --> $DIR/option_map_unit_fn_fixable.rs:48:5 | LL | x.field.map(|value| x.do_option_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -33,7 +33,7 @@ LL | x.field.map(|value| x.do_option_nothing(value + captured)); | help: try this: `if let Some(value) = x.field { x.do_option_nothing(value + captured) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type - --> $DIR/option_map_unit_fn_fixable.rs:46:5 + --> $DIR/option_map_unit_fn_fixable.rs:50:5 | LL | x.field.map(|value| { x.do_option_plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -41,7 +41,7 @@ LL | x.field.map(|value| { x.do_option_plus_one(value + captured); }); | help: try this: `if let Some(value) = x.field { x.do_option_plus_one(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type - --> $DIR/option_map_unit_fn_fixable.rs:49:5 + --> $DIR/option_map_unit_fn_fixable.rs:53:5 | LL | x.field.map(|value| do_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -49,7 +49,7 @@ LL | x.field.map(|value| do_nothing(value + captured)); | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type - --> $DIR/option_map_unit_fn_fixable.rs:51:5 + --> $DIR/option_map_unit_fn_fixable.rs:55:5 | LL | x.field.map(|value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -57,7 +57,7 @@ LL | x.field.map(|value| { do_nothing(value + captured) }); | help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type - --> $DIR/option_map_unit_fn_fixable.rs:53:5 + --> $DIR/option_map_unit_fn_fixable.rs:57:5 | LL | x.field.map(|value| { do_nothing(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -65,7 +65,7 @@ LL | x.field.map(|value| { do_nothing(value + captured); }); | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type - --> $DIR/option_map_unit_fn_fixable.rs:55:5 + --> $DIR/option_map_unit_fn_fixable.rs:59:5 | LL | x.field.map(|value| { { do_nothing(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -73,7 +73,7 @@ LL | x.field.map(|value| { { do_nothing(value + captured); } }); | help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type - --> $DIR/option_map_unit_fn_fixable.rs:58:5 + --> $DIR/option_map_unit_fn_fixable.rs:62:5 | LL | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -81,7 +81,7 @@ LL | x.field.map(|value| diverge(value + captured)); | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type - --> $DIR/option_map_unit_fn_fixable.rs:60:5 + --> $DIR/option_map_unit_fn_fixable.rs:64:5 | LL | x.field.map(|value| { diverge(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -89,7 +89,7 @@ LL | x.field.map(|value| { diverge(value + captured) }); | help: try this: `if let Some(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type - --> $DIR/option_map_unit_fn_fixable.rs:62:5 + --> $DIR/option_map_unit_fn_fixable.rs:66:5 | LL | x.field.map(|value| { diverge(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -97,7 +97,7 @@ LL | x.field.map(|value| { diverge(value + captured); }); | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type - --> $DIR/option_map_unit_fn_fixable.rs:64:5 + --> $DIR/option_map_unit_fn_fixable.rs:68:5 | LL | x.field.map(|value| { { diverge(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -105,7 +105,7 @@ LL | x.field.map(|value| { { diverge(value + captured); } }); | help: try this: `if let Some(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type - --> $DIR/option_map_unit_fn_fixable.rs:69:5 + --> $DIR/option_map_unit_fn_fixable.rs:73:5 | LL | x.field.map(|value| { let y = plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -113,7 +113,7 @@ LL | x.field.map(|value| { let y = plus_one(value + captured); }); | help: try this: `if let Some(value) = x.field { let y = plus_one(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type - --> $DIR/option_map_unit_fn_fixable.rs:71:5 + --> $DIR/option_map_unit_fn_fixable.rs:75:5 | LL | x.field.map(|value| { plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -121,7 +121,7 @@ LL | x.field.map(|value| { plus_one(value + captured); }); | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type - --> $DIR/option_map_unit_fn_fixable.rs:73:5 + --> $DIR/option_map_unit_fn_fixable.rs:77:5 | LL | x.field.map(|value| { { plus_one(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -129,12 +129,20 @@ LL | x.field.map(|value| { { plus_one(value + captured); } }); | help: try this: `if let Some(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type - --> $DIR/option_map_unit_fn_fixable.rs:76:5 + --> $DIR/option_map_unit_fn_fixable.rs:80:5 | -LL | x.field.map(|ref value| { do_nothing(value + captured) });} +LL | x.field.map(|ref value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: try this: `if let Some(ref value) = x.field { do_nothing(value + captured) }` -error: aborting due to 17 previous errors +error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type + --> $DIR/option_map_unit_fn_fixable.rs:82:5 + | +LL | option().map(do_nothing);} + | ^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Some(a) = option() { do_nothing(a) }` + +error: aborting due to 18 previous errors From 58dec1ca9c98cfb46d6152fe222cd37d635b143e Mon Sep 17 00:00:00 2001 From: Chris Simpkins Date: Mon, 9 Mar 2020 17:58:39 -0400 Subject: [PATCH 192/243] update rust-lang.github.io to rustc-dev-guide.rust-lang.org --- doc/adding_lints.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/adding_lints.md b/doc/adding_lints.md index 1e78b0801d88..4572a9a334f7 100644 --- a/doc/adding_lints.md +++ b/doc/adding_lints.md @@ -459,5 +459,5 @@ don't hesitate to ask on Discord, IRC or in the issue/PR. [in_external_macro]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/fn.in_external_macro.html [play]: https://play.rust-lang.org [author_example]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=f093b986e80ad62f3b67a1f24f5e66e2 -[rustc-dev-guide]: https://rust-lang.github.io/rustc-dev-guide/ +[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/ [nightly_docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ From 5fd74a9a6a08d6e5ee116ed032d8e90cb1fd2b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Tue, 10 Mar 2020 01:05:17 +0100 Subject: [PATCH 193/243] clippy_lints: readme: don't mention crates.io since it is no longer used to publish clippy. --- clippy_lints/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/clippy_lints/README.md b/clippy_lints/README.md index 2724aa6a0523..513583b7e349 100644 --- a/clippy_lints/README.md +++ b/clippy_lints/README.md @@ -1,3 +1 @@ -This crate contains Clippy lints. For the main crate, check -[*crates.io*](https://crates.io/crates/clippy) or -[GitHub](https://github.com/rust-lang/rust-clippy). +This crate contains Clippy lints. For the main crate, check [GitHub](https://github.com/rust-lang/rust-clippy). From a3d9355bef01aaefb9b6f3fb53b88cd4ce156453 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 10 Mar 2020 13:17:15 +0900 Subject: [PATCH 194/243] Fix ICE with trivial_bounds feature --- clippy_lints/src/implicit_return.rs | 8 +++++++- clippy_lints/src/missing_const_for_fn.rs | 7 ++++++- clippy_lints/src/redundant_clone.rs | 10 ++++++++-- clippy_lints/src/utils/mod.rs | 23 ++++++++++++++++++++++- tests/ui/crashes/trivial_bounds.rs | 13 +++++++++++++ 5 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 tests/ui/crashes/trivial_bounds.rs diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index b0d80aa0d539..d968a928c33b 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -1,5 +1,5 @@ use crate::utils::{ - match_def_path, + fn_has_unsatisfiable_preds, match_def_path, paths::{BEGIN_PANIC, BEGIN_PANIC_FMT}, snippet_opt, span_lint_and_then, }; @@ -133,6 +133,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitReturn { _: HirId, ) { let def_id = cx.tcx.hir().body_owner_def_id(body.id()); + + // Building MIR for `fn`s with unsatisfiable preds results in ICE. + if fn_has_unsatisfiable_preds(cx, def_id) { + return; + } + let mir = cx.tcx.optimized_mir(def_id); // checking return type through MIR, HIR is not able to determine inferred closure return types diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index e829baa22688..a22d8b4cf9eb 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -1,4 +1,4 @@ -use crate::utils::{has_drop, is_entrypoint_fn, span_lint, trait_ref_of_method}; +use crate::utils::{fn_has_unsatisfiable_preds, has_drop, is_entrypoint_fn, span_lint, trait_ref_of_method}; use rustc::lint::in_external_macro; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; @@ -88,6 +88,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn { return; } + // Building MIR for `fn`s with unsatisfiable preds results in ICE. + if fn_has_unsatisfiable_preds(cx, def_id) { + return; + } + // Perform some preliminary checks that rule out constness on the Clippy side. This way we // can skip the actual const check and return early. match kind { diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index ddb0c7484348..103c063aef4b 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -1,6 +1,6 @@ use crate::utils::{ - has_drop, is_copy, match_def_path, match_type, paths, snippet_opt, span_lint_hir, span_lint_hir_and_then, - walk_ptrs_ty_depth, + fn_has_unsatisfiable_preds, has_drop, is_copy, match_def_path, match_type, paths, snippet_opt, span_lint_hir, + span_lint_hir_and_then, walk_ptrs_ty_depth, }; use if_chain::if_chain; use matches::matches; @@ -79,6 +79,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { _: HirId, ) { let def_id = cx.tcx.hir().body_owner_def_id(body.id()); + + // Building MIR for `fn`s with unsatisfiable preds results in ICE. + if fn_has_unsatisfiable_preds(cx, def_id) { + return; + } + let mir = cx.tcx.optimized_mir(def_id); let mir_read_only = mir.unwrap_read_only(); diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index dc8775b43b19..a27245fd234b 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -32,7 +32,7 @@ use rustc::ty::{ self, layout::{self, IntegerExt}, subst::GenericArg, - Binder, Ty, TyCtxt, + Binder, Ty, TyCtxt, TypeFoldable, }; use rustc_ast::ast::{self, Attribute, LitKind}; use rustc_attr as attr; @@ -1377,6 +1377,27 @@ pub fn is_trait_impl_item(cx: &LateContext<'_, '_>, hir_id: HirId) -> bool { } } +/// Check if it's even possible to satisfy the `where` clause for the item. +/// +/// `trivial_bounds` feature allows functions with unsatisfiable bounds, for example: +/// +/// ```rust +/// fn foo() i32: Iterator { +/// for _ in 2i32 {} +/// } +/// ``` +pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_, '_>, did: DefId) -> bool { + use rustc_infer::traits; + let predicates = cx + .tcx + .predicates_of(did) + .predicates + .iter() + .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }) + .collect(); + !traits::normalize_and_test_predicates(cx.tcx, traits::elaborate_predicates(cx.tcx, predicates).collect()) +} + #[cfg(test)] mod test { use super::{trim_multiline, without_block_comments}; diff --git a/tests/ui/crashes/trivial_bounds.rs b/tests/ui/crashes/trivial_bounds.rs new file mode 100644 index 000000000000..2bb95c18a391 --- /dev/null +++ b/tests/ui/crashes/trivial_bounds.rs @@ -0,0 +1,13 @@ +// run-pass + +#![feature(trivial_bounds)] +#![allow(unused, trivial_bounds)] + +fn test_trivial_bounds() +where + i32: Iterator, +{ + for _ in 2i32 {} +} + +fn main() {} From 227ef60a2b2fd3d78eb39d4361efc224be38cbb6 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 10 Mar 2020 13:27:33 +0900 Subject: [PATCH 195/243] Fix doc --- clippy_lints/src/utils/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index a27245fd234b..9f7cf4007657 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1381,8 +1381,8 @@ pub fn is_trait_impl_item(cx: &LateContext<'_, '_>, hir_id: HirId) -> bool { /// /// `trivial_bounds` feature allows functions with unsatisfiable bounds, for example: /// -/// ```rust -/// fn foo() i32: Iterator { +/// ```ignore +/// fn foo() where i32: Iterator { /// for _ in 2i32 {} /// } /// ``` From 8d2a3e0a61dbcf2ec6ce5a693c68e3da587991b9 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 10 Mar 2020 18:18:34 +0900 Subject: [PATCH 196/243] Use `node_type_opt` over `node_type` --- clippy_lints/src/shadow.rs | 12 ++++++++---- tests/ui/crashes/shadow.rs | 6 ++++++ 2 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 tests/ui/crashes/shadow.rs diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 0dc2705550b9..0ada65ec7855 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -154,10 +154,14 @@ fn check_local<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, local: &'tcx Local<'_>, bin } fn is_binding(cx: &LateContext<'_, '_>, pat_id: HirId) -> bool { - let var_ty = cx.tables.node_type(pat_id); - match var_ty.kind { - ty::Adt(..) => false, - _ => true, + let var_ty = cx.tables.node_type_opt(pat_id); + if let Some(var_ty) = var_ty { + match var_ty.kind { + ty::Adt(..) => false, + _ => true, + } + } else { + false } } diff --git a/tests/ui/crashes/shadow.rs b/tests/ui/crashes/shadow.rs new file mode 100644 index 000000000000..843e8ef64dcd --- /dev/null +++ b/tests/ui/crashes/shadow.rs @@ -0,0 +1,6 @@ +fn main() { + let x: [i32; { + let u = 2; + 4 + }] = [2; { 4 }]; +} From 2fa3da486924b9c8807308fa00b7be6ae1adc167 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Tue, 10 Mar 2020 20:19:37 +0100 Subject: [PATCH 197/243] needless_doc_main: only check rust code --- clippy_lints/src/doc.rs | 22 +++++++++++++++---- tests/ui/needless_doc_main.rs | 36 +++++++++++++++++++++++++++++-- tests/ui/needless_doc_main.stderr | 14 +++++++++++- 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 35578ae68a46..754d38f40158 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -367,6 +367,8 @@ fn check_attrs<'a>(cx: &LateContext<'_, '_>, valid_idents: &FxHashSet, a check_doc(cx, valid_idents, events, &spans) } +const RUST_CODE: &[&str] = &["rust", "no_run", "should_panic", "compile_fail", "edition2018"]; + fn check_doc<'a, Events: Iterator, Range)>>( cx: &LateContext<'_, '_>, valid_idents: &FxHashSet, @@ -374,6 +376,7 @@ fn check_doc<'a, Events: Iterator, Range DocHeaders { // true if a safety header was found + use pulldown_cmark::CodeBlockKind; use pulldown_cmark::Event::{ Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text, }; @@ -386,11 +389,20 @@ fn check_doc<'a, Events: Iterator, Range in_code = true, - End(CodeBlock(_)) => in_code = false, + Start(CodeBlock(ref kind)) => { + in_code = true; + if let CodeBlockKind::Fenced(lang) = kind { + is_rust = + lang.is_empty() || !lang.contains("ignore") && lang.split(',').any(|i| RUST_CODE.contains(&i)); + } + }, + End(CodeBlock(_)) => { + in_code = false; + is_rust = false; + }, Start(Link(_, url, _)) => in_link = Some(url), End(Link(..)) => in_link = None, Start(Heading(_)) => in_heading = true, @@ -413,7 +425,9 @@ fn check_doc<'a, Events: Iterator, Range $DIR/needless_doc_main.rs:15:4 + | +LL | /// fn main() { + | ^^^^^^^^^^^^ + +error: needless `fn main` in doctest + --> $DIR/needless_doc_main.rs:23:4 + | +LL | /// fn main() { + | ^^^^^^^^^^^^ + +error: aborting due to 3 previous errors From 8cdd75ca2965a5618c763eb751cf2dec5b4a66c2 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 10 Mar 2020 18:50:06 +0900 Subject: [PATCH 198/243] Clean-up CONTRIBUTING.md --- CONTRIBUTING.md | 79 ++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 44 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3fc9b14e8a73..23e371774785 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,8 +8,7 @@ something. We appreciate any sort of contributions, and don't want a wall of rul Clippy welcomes contributions from everyone. There are many ways to contribute to Clippy and the following document explains how you can contribute and how to get started. If you have any questions about contributing or need help with -anything, feel free to ask questions on issues or visit the `#clippy` IRC channel on `irc.mozilla.org` or meet us in -`#clippy` on [Discord](https://discord.gg/rust-lang). +anything, feel free to ask questions on issues or visit the `#clippy` on [Discord](https://discord.gg/rust-lang). All contributors are expected to follow the [Rust Code of Conduct](http://www.rust-lang.org/conduct.html). @@ -55,8 +54,7 @@ and resolved paths. [`T-AST`](https://github.com/rust-lang/rust-clippy/labels/T-AST) issues will generally need you to match against a predefined syntax structure. To figure out how this syntax structure is encoded in the AST, it is recommended to run `rustc -Z ast-json` on an example of the structure and compare with the [nodes in the AST -docs](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/ast). Usually the lint will end up to be a nested series of -matches and ifs, [like +docs]. Usually the lint will end up to be a nested series of matches and ifs, [like so](https://github.com/rust-lang/rust-clippy/blob/de5ccdfab68a5e37689f3c950ed1532ba9d652a0/src/misc.rs#L34). [`E-medium`](https://github.com/rust-lang/rust-clippy/labels/E-medium) issues are generally @@ -69,6 +67,8 @@ be more involved and require verifying types. The lot of methods that are useful, though one of the most useful would be `expr_ty` (gives the type of an AST expression). `match_def_path()` in Clippy's `utils` module can also be useful. +[nodes in the AST docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/ + ## Writing code Have a look at the [docs for writing lints](doc/adding_lints.md) for more details. [Llogiq's blog post on @@ -82,11 +82,8 @@ quick read. ## How Clippy works -Clippy is a [rustc compiler plugin][compiler_plugin]. The main entry point is at [`src/lib.rs`][main_entry]. In there, -the lint registration is delegated to the [`clippy_lints`][lint_crate] crate. - -[`clippy_lints/src/lib.rs`][lint_crate_entry] imports all the different lint modules and registers them with the rustc -plugin registry. For example, the [`else_if_without_else`][else_if_without_else] lint is registered like this: +[`clippy_lints/src/lib.rs`][lint_crate_entry] imports all the different lint modules and registers in the [`LintStore`]. +For example, the [`else_if_without_else`][else_if_without_else] lint is registered like this: ```rust // ./clippy_lints/src/lib.rs @@ -95,25 +92,24 @@ plugin registry. For example, the [`else_if_without_else`][else_if_without_else] pub mod else_if_without_else; // ... -pub fn register_plugins(reg: &mut rustc_driver::plugin::Registry) { +pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &Conf) { // ... - reg.register_early_lint_pass(box else_if_without_else::ElseIfWithoutElse); + store.register_early_pass(|| box else_if_without_else::ElseIfWithoutElse); // ... - reg.register_lint_group("clippy::restriction", vec![ + store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ // ... - else_if_without_else::ELSE_IF_WITHOUT_ELSE, + LintId::of(&else_if_without_else::ELSE_IF_WITHOUT_ELSE), // ... ]); } ``` -The [`plugin::PluginRegistry`][plugin_registry] provides two methods to register lints: -[register_early_lint_pass][reg_early_lint_pass] and [register_late_lint_pass][reg_late_lint_pass]. Both take an object +The [`rustc_lint::LintStore`][`LintStore`] provides two methods to register lints: +[register_early_pass][reg_early_pass] and [register_late_pass][reg_late_pass]. Both take an object that implements an [`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass] respectively. This is done in every single lint. It's worth noting that the majority of `clippy_lints/src/lib.rs` is autogenerated by `cargo dev -update_lints` and you don't have to add anything by hand. When you are writing your own lint, you can use that script to -save you some time. +update_lints`. When you are writing your own lint, you can use that script to save you some time. ```rust // ./clippy_lints/src/else_if_without_else.rs @@ -135,9 +131,14 @@ The difference between `EarlyLintPass` and `LateLintPass` is that the methods of AST information. The methods of the `LateLintPass` trait are executed after type checking and contain type information via the `LateContext` parameter. -That's why the `else_if_without_else` example uses the `register_early_lint_pass` function. Because the [actual lint +That's why the `else_if_without_else` example uses the `register_early_pass` function. Because the [actual lint logic][else_if_without_else] does not depend on any type information. +See also [the adding lints doc]. + +[the adding lints doc]: https://github.com/rust-lang/rust-clippy/blob/master/doc/adding_lints.md +[`LintStore`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html + ## Fixing build failures caused by Rust Clippy will sometimes fail to build from source because building it depends on unstable internal Rust features. Most of @@ -145,8 +146,9 @@ the times we have to adapt to the changes and only very rarely there's an actual caused by Rust updates, can be a good way to learn about Rust internals. In order to find out why Clippy does not work properly with a new Rust commit, you can use the [rust-toolstate commit -history][toolstate_commit_history]. You will then have to look for the last commit that contains `test-pass -> -build-fail` or `test-pass` -> `test-fail` for the `clippy-driver` component. [Here][toolstate_commit] is an example. +history][toolstate_commit_history]. You will then have to look for the last commit that contains +`test-pass -> build-fail` or `test-pass` -> `test-fail` for the `clippy-driver` component. +[Here][toolstate_commit] is an example. The commit message contains a link to the PR. The PRs are usually small enough to discover the breaking API change and if they are bigger, they likely include some discussion that may help you to fix Clippy. @@ -158,14 +160,8 @@ If you decide to make Clippy work again with a Rust commit that breaks it, you probably want to install the latest Rust from master locally and run Clippy using that version of Rust. -You can use [rustup-toolchain-install-master][rtim] to do that: - -```bash -cargo install rustup-toolchain-install-master -rustup-toolchain-install-master --force -n master -c rustc-dev -rustup override set master -cargo test -``` +You can set up the master toolchain by running `./setup-toolchain.sh`. That script will install +[rustup-toolchain-install-master][rtim] and master toolchain, then run `rustup override set master`. After fixing the build failure on this repository, we can submit a pull request to [`rust-lang/rust`] to fix the toolstate. @@ -206,39 +202,34 @@ You can find the Clippy bors queue [here][homu_queue]. If you have @bors permissions, you can find an overview of the available commands [here][homu_instructions]. - ## Contributions Contributions to Clippy should be made in the form of GitHub pull requests. Each pull request will be reviewed by a core contributor (someone with permission to land patches) and either landed in the main tree or given feedback for changes that would be required. -All code in this repository is under the [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0>) -or the [MIT](http://opensource.org/licenses/MIT) license. +All code in this repository is under the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0) +or the [MIT](https://opensource.org/licenses/MIT) license. -[main_entry]: https://github.com/rust-lang/rust-clippy/blob/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/src/lib.rs#L14 -[lint_crate]: https://github.com/rust-lang/rust-clippy/tree/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/clippy_lints/src -[lint_crate_entry]: https://github.com/rust-lang/rust-clippy/blob/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/clippy_lints/src/lib.rs -[else_if_without_else]: https://github.com/rust-lang/rust-clippy/blob/c5b39a5917ffc0f1349b6e414fa3b874fdcf8429/clippy_lints/src/else_if_without_else.rs -[compiler_plugin]: https://doc.rust-lang.org/unstable-book/language-features/plugin.html#lint-plugins -[plugin_registry]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_plugin_impl/registry/struct.Registry.html -[reg_early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_plugin_impl/registry/struct.Registry.html#method.register_early_lint_pass -[reg_late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_plugin_impl/registry/struct.Registry.html#method.register_late_lint_pass -[early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/trait.EarlyLintPass.html -[late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/trait.LateLintPass.html +[lint_crate_entry]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/lib.rs +[else_if_without_else]: https://github.com/rust-lang/rust-clippy/blob/4253aa7137cb7378acc96133c787e49a345c2b3c/clippy_lints/src/else_if_without_else.rs +[reg_early_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_early_pass +[reg_late_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_late_pass +[early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html +[late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html [toolstate_commit_history]: https://github.com/rust-lang-nursery/rust-toolstate/commits/master -[toolstate_commit]: https://github.com/rust-lang-nursery/rust-toolstate/commit/6ce0459f6bfa7c528ae1886492a3e0b5ef0ee547 +[toolstate_commit]: https://github.com/rust-lang-nursery/rust-toolstate/commit/aad74d8294e198a7cf8ac81a91aebb7f3bbcf727 [rtim]: https://github.com/kennytm/rustup-toolchain-install-master -[rustup_component_history]: https://mexus.github.io/rustup-components-history +[rustup_component_history]: https://rust-lang.github.io/rustup-components-history [clippy_rfc]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md [rfc_stability]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#stability-guarantees [rfc_lint_cats]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#lint-audit-and-categories [triage]: https://forge.rust-lang.org/triage-procedure.html [l-crash]: https://github.com/rust-lang/rust-clippy/labels/L-crash%20%3Aboom%3A [l-bug]: https://github.com/rust-lang/rust-clippy/labels/L-bug%20%3Abeetle%3A -[homu]: https://github.com/servo/homu +[homu]: https://github.com/rust-lang/homu [homu_instructions]: https://buildbot2.rust-lang.org/homu/ [homu_queue]: https://buildbot2.rust-lang.org/homu/queue/clippy [`rust-lang/rust`]: https://github.com/rust-lang/rust From 459fb53f8d3f3d4a5c6145b9940a04979ee83e71 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 11 Mar 2020 05:21:28 +0900 Subject: [PATCH 199/243] Clean-up adding_lints.md --- doc/adding_lints.md | 99 ++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 50 deletions(-) diff --git a/doc/adding_lints.md b/doc/adding_lints.md index 4572a9a334f7..54034f664834 100644 --- a/doc/adding_lints.md +++ b/doc/adding_lints.md @@ -1,4 +1,4 @@ -## Adding a new lint +# Adding a new lint You are probably here because you want to add a new lint to Clippy. If this is the first time you're contributing to Clippy, this document guides you through @@ -25,14 +25,14 @@ because that's clearly a non-descriptive name. - [PR Checklist](#pr-checklist) - [Cheatsheet](#cheatsheet) -### Setup +## Setup When working on Clippy, you will need the current git master version of rustc, which can change rapidly. Make sure you're working near rust-clippy's master, and use the `setup-toolchain.sh` script to configure the appropriate toolchain for the Clippy directory. -### Getting Started +## Getting Started There is a bit of boilerplate code that needs to be set up when creating a new lint. Fortunately, you can use the clippy dev tools to handle this for you. We @@ -45,7 +45,7 @@ two files: `tests/ui/foo_functions.rs` and `clippy_lints/src/foo_functions.rs`, as well as run `cargo dev update_lints` to register the new lint. Next, we'll open up these files and add our lint! -### Testing +## Testing Let's write some tests first that we can execute while we iterate on our lint. @@ -88,12 +88,10 @@ fn main() { let a = A; a.foo(); } - ``` -Now we can run the test with `TESTNAME=foo_functions cargo uitest`. -Currently this test will fail. If you go through the output you will see that we -are told that `clippy::foo_functions` is an unknown lint, which is expected. +Now we can run the test with `TESTNAME=foo_functions cargo uitest`, +currently this test is meaningless though. While we are working on implementing our lint, we can keep running the UI test. That allows us to check if the output is turning into what we want. @@ -105,7 +103,7 @@ every time before running `tests/ui/update-all-references.sh`. Running `TESTNAME=foo_functions cargo uitest` should pass then. When we commit our lint, we need to commit the generated `.stderr` files, too. -### Rustfix tests +## Rustfix tests 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 @@ -116,13 +114,13 @@ 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 the tests. -### Edition 2018 tests +## Edition 2018 tests Some features require the 2018 edition to work (e.g. `async_await`), but compile-test tests run on the 2015 edition by default. To change this behavior -add `// compile-flags: --edition 2018` at the top of the test file. +add `// edition:2018` at the top of the test file (note that it's space-sensitive). -### Testing manually +## Testing manually Manually testing against an example file can be useful if you have added some `println!`s and the test suite output becomes unreadable. To try Clippy with @@ -131,7 +129,7 @@ clippy-driver -- -L ./target/debug input.rs` from the working copy root. With tests in place, let's have a look at implementing our lint now. -### Lint declaration +## Lint declaration Let's start by opening the new file created in the `clippy_lints` crate at `clippy_lints/src/foo_functions.rs`. That's the crate where all the @@ -140,7 +138,7 @@ lint code is. This file has already imported some initial things we will need: ```rust use rustc_lint::{EarlyLintPass, EarlyContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use syntax::ast::*; +use rustc_ast::ast::*; ``` The next step is to update the lint declaration. Lints are declared using the @@ -167,8 +165,8 @@ declare_clippy_lint! { ``` * The section of lines prefixed with `///` constitutes the lint documentation - section. This is the default documentation style and will be displayed at - https://rust-lang.github.io/rust-clippy/master/index.html. + section. This is the default documentation style and will be displayed + [like this][example_lint_page]. * `FOO_FUNCTIONS` is the name of our lint. Be sure to follow the [lint naming guidelines][lint_naming] here when naming your lint. In short, the name should state the thing that is being checked for and read well when used with @@ -199,14 +197,12 @@ automate everything. We will have to register our lint pass manually in the `register_plugins` function in `clippy_lints/src/lib.rs`: ```rust -store.register_early_pass(box foo_functions::FooFunctions); +store.register_early_pass(|| box foo_functions::FooFunctions); ``` -This should fix the `unknown clippy lint: clippy::foo_functions` error that we -saw when we executed our tests the first time. The next decision we have to make -is which lint pass our lint is going to need. +[example lint page]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure -### Lint passes +## Lint passes Writing a lint that only checks for the name of a function means that we only have to deal with the AST and don't have to deal with the type system at all. @@ -224,7 +220,7 @@ Since we don't need type information for checking the function name, we used `--pass=early` when running the new lint automation and all the imports were added accordingly. -### Emitting a lint +## Emitting a lint With UI tests and the lint declaration in place, we can start working on the implementation of the lint logic. @@ -233,7 +229,7 @@ Let's start by implementing the `EarlyLintPass` for our `FooFunctions`: ```rust impl EarlyLintPass for FooFunctions { - fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, _: &FnDecl, span: Span, _: NodeId) { + fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, span: Span, _: NodeId) { // TODO: Emit lint here } } @@ -255,7 +251,7 @@ automatically. This is how it looks: ```rust impl EarlyLintPass for FooFunctions { - fn check_fn(&mut self, cx: &EarlyContext<'_>, _: FnKind<'_>, _: &FnDecl, span: Span, _: NodeId) { + fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, span: Span, _: NodeId) { span_lint_and_help( cx, FOO_FUNCTIONS, @@ -269,20 +265,20 @@ impl EarlyLintPass for FooFunctions { Running our UI test should now produce output that contains the lint message. -### Adding the lint logic +## Adding the lint logic Writing the logic for your lint will most likely be different from our example, so this section is kept rather short. Using the [`check_fn`][check_fn] method gives us access to [`FnKind`][fn_kind] -that has two relevant variants for us `FnKind::ItemFn` and `FnKind::Method`. -Both provide access to the name of the function/method via an [`Ident`][ident]. +that has the `FnKind::Fn` variant. It provides access to the name of the +function/method via an [`Ident`][ident]. With that we can expand our `check_fn` method to: ```rust impl EarlyLintPass for FooFunctions { - fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, _: &FnDecl, span: Span, _: NodeId) { + fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, span: Span, _: NodeId) { if is_foo_fn(fn_kind) { span_lint_and_help( cx, @@ -307,9 +303,11 @@ In our example, `is_foo_fn` looks like: fn is_foo_fn(fn_kind: FnKind<'_>) -> bool { match fn_kind { - FnKind::ItemFn(ident, ..) | FnKind::Method(ident, ..) => { - ident.name == "foo" - }, + FnKind::Fn(_, ident, ..) => { + // check if `fn` name is `foo` + ident.name.as_str() == "foo" + } + // ignore closures FnKind::Closure(..) => false } } @@ -325,13 +323,14 @@ implementation is not violating any Clippy lints itself. That should be it for the lint implementation. Running `cargo test` should now pass. -### Author lint +## Author lint If you have trouble implementing your lint, there is also the internal `author` lint to generate Clippy code that detects the offending pattern. It does not work for all of the Rust syntax, but can give a good starting point. -The quickest way to use it, is the [Rust playground: play.rust-lang.org][Play]. +The quickest way to use it, is the +[Rust playground: play.rust-lang.org][author_example]. Put the code you want to lint into the editor and add the `#[clippy::author]` attribute above the item. Then run Clippy via `Tools -> Clippy` and you should see the generated code in the output below. @@ -341,7 +340,7 @@ see the generated code in the output below. If the command was executed successfully, you can copy the code over to where you are implementing your lint. -### Documentation +## Documentation The final thing before submitting our PR is to add some documentation to our lint declaration. @@ -374,7 +373,7 @@ declare_clippy_lint! { Once your lint is merged, this documentation will show up in the [lint list][lint_list]. -### Running rustfmt +## Running rustfmt [Rustfmt](https://github.com/rust-lang/rustfmt) is a tool for formatting Rust code according to style guidelines. Your code has to be formatted by `rustfmt` @@ -389,13 +388,13 @@ rustup component add rustfmt --toolchain=nightly Use `cargo dev fmt` to format the whole codebase. Make sure that `rustfmt` is installed for the nightly toolchain. -### Debugging +## Debugging -If you want to debug parts of your lint implementation, you can use the `dbg!` +If you want to debug parts of your lint implementation, you can use the [`dbg!`] macro anywhere in your code. Running the tests should then include the debug output in the `stdout` part. -### PR Checklist +## PR Checklist Before submitting your PR make sure you followed all of the basic requirements: @@ -408,7 +407,7 @@ Before submitting your PR make sure you followed all of the basic requirements: - [ ] Added lint documentation - [ ] Run `cargo dev fmt` -### Cheatsheet +## Cheatsheet Here are some pointers to things you are likely going to need for every lint: @@ -426,38 +425,38 @@ Here are some pointers to things you are likely going to need for every lint: For `EarlyLintPass` lints: * [`EarlyLintPass`][early_lint_pass] -* [`syntax::ast`][ast] +* [`rustc_ast::ast`][ast] For `LateLintPass` lints: * [`LateLintPass`][late_lint_pass] * [`Ty::TyKind`][ty] - While most of Clippy's lint utils are documented, most of rustc's internals lack documentation currently. This is unfortunate, but in most cases you can probably get away with copying things from existing similar lints. If you are stuck, -don't hesitate to ask on Discord, IRC or in the issue/PR. +don't hesitate to ask on [Discord] or in the issue/PR. [lint_list]: https://rust-lang.github.io/rust-clippy/master/index.html [lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints [category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/bd23cb89ec0ea63403a17d3fc5e50c88e38dd54f/clippy_lints/src/lib.rs#L43 [declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/a71acac1da7eaf667ab90a1d65d10e5cc4b80191/clippy_lints/src/lib.rs#L39 -[check_fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/trait.EarlyLintPass.html#method.check_fn -[early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/trait.EarlyLintPass.html -[late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/trait.LateLintPass.html -[fn_kind]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/visit/enum.FnKind.html +[check_fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html#method.check_fn +[early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html +[late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html +[fn_kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/visit/enum.FnKind.html [diagnostics]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/utils/diagnostics.rs [utils]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/utils/mod.rs -[ident]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/source_map/symbol/struct.Ident.html +[ident]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Ident.html [span]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html [applicability]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/enum.Applicability.html [if_chain]: https://docs.rs/if_chain/*/if_chain/ [ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/sty/index.html -[ast]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/ast/index.html +[ast]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/index.html [from_expansion]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html#method.from_expansion [in_external_macro]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/fn.in_external_macro.html -[play]: https://play.rust-lang.org -[author_example]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=f093b986e80ad62f3b67a1f24f5e66e2 +[author_example]: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=9a12cb60e5c6ad4e3003ac6d5e63cf55 [rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/ [nightly_docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ +[Discord]: https://discord.gg/rust-lang +[`dbg`!]: https://doc.rust-lang.org/std/macro.dbg.html From 19e72a24ae43084d8bb2b14ad3ff88391e1148d9 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 11 Mar 2020 05:40:53 +0900 Subject: [PATCH 200/243] Move links to the end of each chapter on CONTRIBUTING --- CONTRIBUTING.md | 112 +++++++++++++++++++++++++----------------------- 1 file changed, 59 insertions(+), 53 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 23e371774785..b52266ac4f1b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,9 +8,9 @@ something. We appreciate any sort of contributions, and don't want a wall of rul Clippy welcomes contributions from everyone. There are many ways to contribute to Clippy and the following document explains how you can contribute and how to get started. If you have any questions about contributing or need help with -anything, feel free to ask questions on issues or visit the `#clippy` on [Discord](https://discord.gg/rust-lang). +anything, feel free to ask questions on issues or visit the `#clippy` on [Discord]. -All contributors are expected to follow the [Rust Code of Conduct](http://www.rust-lang.org/conduct.html). +All contributors are expected to follow the [Rust Code of Conduct]. * [Getting started](#getting-started) * [Finding something to fix/improve](#finding-something-to-fiximprove) @@ -21,6 +21,9 @@ All contributors are expected to follow the [Rust Code of Conduct](http://www.ru * [Bors and Homu](#bors-and-homu) * [Contributions](#contributions) +[Discord]: https://discord.gg/rust-lang +[Rust Code of Conduct]: https://www.rust-lang.org/policies/code-of-conduct + ## Getting started High level approach: @@ -35,51 +38,57 @@ High level approach: All issues on Clippy are mentored, if you want help with a bug just ask @Manishearth, @llogiq, @mcarton or @oli-obk. -Some issues are easier than others. The [`good first issue`](https://github.com/rust-lang/rust-clippy/labels/good%20first%20issue) -label can be used to find the easy issues. If you want to work on an issue, please leave a comment -so that we can assign it to you! +Some issues are easier than others. The [`good first issue`] label can be used to find the easy issues. +If you want to work on an issue, please leave a comment so that we can assign it to you! -There are also some abandoned PRs, marked with -[`S-inactive-closed`](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Aclosed+label%3AS-inactive-closed). +There are also some abandoned PRs, marked with [`S-inactive-closed`]. Pretty often these PRs are nearly completed and just need some extra steps (formatting, addressing review comments, ...) to be merged. If you want to complete such a PR, please leave a comment in the PR and open a new one based on it. -Issues marked [`T-AST`](https://github.com/rust-lang/rust-clippy/labels/T-AST) involve simple -matching of the syntax tree structure, and are generally easier than -[`T-middle`](https://github.com/rust-lang/rust-clippy/labels/T-middle) issues, which involve types +Issues marked [`T-AST`] involve simple matching of the syntax tree structure, +and are generally easier than [`T-middle`] issues, which involve types and resolved paths. -[`T-AST`](https://github.com/rust-lang/rust-clippy/labels/T-AST) issues will generally need you to match against a -predefined syntax structure. To figure out how this syntax structure is encoded in the AST, it is recommended to run -`rustc -Z ast-json` on an example of the structure and compare with the [nodes in the AST -docs]. Usually the lint will end up to be a nested series of matches and ifs, [like -so](https://github.com/rust-lang/rust-clippy/blob/de5ccdfab68a5e37689f3c950ed1532ba9d652a0/src/misc.rs#L34). +[`T-AST`] issues will generally need you to match against a predefined syntax structure. +To figure out how this syntax structure is encoded in the AST, it is recommended to run +`rustc -Z ast-json` on an example of the structure and compare with the [nodes in the AST docs]. +Usually the lint will end up to be a nested series of matches and ifs, [like so]. -[`E-medium`](https://github.com/rust-lang/rust-clippy/labels/E-medium) issues are generally -pretty easy too, though it's recommended you work on an E-easy issue first. They are mostly classified -as `E-medium`, since they might be somewhat involved code wise, but not difficult per-se. +[`E-medium`] issues are generally pretty easy too, though it's recommended you work on an E-easy issue first. +They are mostly classified as [`E-medium`], since they might be somewhat involved code wise, +but not difficult per-se. -[`T-middle`](https://github.com/rust-lang/rust-clippy/labels/T-middle) issues can -be more involved and require verifying types. The -[`ty`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty) module contains a +[`T-middle`] issues can be more involved and require verifying types. The [`ty`] module contains a lot of methods that are useful, though one of the most useful would be `expr_ty` (gives the type of an AST expression). `match_def_path()` in Clippy's `utils` module can also be useful. +[`good first issue`]: https://github.com/rust-lang/rust-clippy/labels/good%20first%20issue +[`S-inactive-closed`]: https://github.com/rust-lang/rust-clippy/pulls?q=is%3Aclosed+label%3AS-inactive-closed +[`T-AST`]: https://github.com/rust-lang/rust-clippy/labels/T-AST +[`T-middle`]: https://github.com/rust-lang/rust-clippy/labels/T-middle +[`E-medium`]: https://github.com/rust-lang/rust-clippy/labels/E-medium +[`ty`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty [nodes in the AST docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/ +[like so]: https://github.com/rust-lang/rust-clippy/blob/de5ccdfab68a5e37689f3c950ed1532ba9d652a0/src/misc.rs#L34 ## Writing code -Have a look at the [docs for writing lints](doc/adding_lints.md) for more details. [Llogiq's blog post on -lints](https://llogiq.github.io/2015/06/04/workflows.html) is also a nice primer to lint-writing, though it does get -into advanced stuff and may be a bit outdated. +Have a look at the [docs for writing lints][adding_lints] for more details. [Llogiq's blog post on lints] +is also a nice primer to lint-writing, though it does get into advanced stuff and may be a bit outdated. If you want to add a new lint or change existing ones apart from bugfixing, it's also a good idea to give the [stability guarantees][rfc_stability] and [lint categories][rfc_lint_cats] sections of the [Clippy 1.0 RFC][clippy_rfc] a quick read. +[adding_lints]: https://github.com/rust-lang/rust-clippy/blob/master/doc/adding_lints.md +[Llogiq's blog post on lints]: https://llogiq.github.io/2015/06/04/workflows.html +[clippy_rfc]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md +[rfc_stability]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#stability-guarantees +[rfc_lint_cats]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#lint-audit-and-categories + ## How Clippy works [`clippy_lints/src/lib.rs`][lint_crate_entry] imports all the different lint modules and registers in the [`LintStore`]. @@ -131,13 +140,16 @@ The difference between `EarlyLintPass` and `LateLintPass` is that the methods of AST information. The methods of the `LateLintPass` trait are executed after type checking and contain type information via the `LateContext` parameter. -That's why the `else_if_without_else` example uses the `register_early_pass` function. Because the [actual lint -logic][else_if_without_else] does not depend on any type information. - -See also [the adding lints doc]. +That's why the `else_if_without_else` example uses the `register_early_pass` function. Because the +[actual lint logic][else_if_without_else] does not depend on any type information. -[the adding lints doc]: https://github.com/rust-lang/rust-clippy/blob/master/doc/adding_lints.md +[lint_crate_entry]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/lib.rs +[else_if_without_else]: https://github.com/rust-lang/rust-clippy/blob/4253aa7137cb7378acc96133c787e49a345c2b3c/clippy_lints/src/else_if_without_else.rs [`LintStore`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html +[reg_early_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_early_pass +[reg_late_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_late_pass +[early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html +[late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html ## Fixing build failures caused by Rust @@ -146,8 +158,8 @@ the times we have to adapt to the changes and only very rarely there's an actual caused by Rust updates, can be a good way to learn about Rust internals. In order to find out why Clippy does not work properly with a new Rust commit, you can use the [rust-toolstate commit -history][toolstate_commit_history]. You will then have to look for the last commit that contains -`test-pass -> build-fail` or `test-pass` -> `test-fail` for the `clippy-driver` component. +history][toolstate_commit_history]. You will then have to look for the last commit that contains +`test-pass -> build-fail` or `test-pass -> test-fail` for the `clippy-driver` component. [Here][toolstate_commit] is an example. The commit message contains a link to the PR. The PRs are usually small enough to discover the breaking API change and @@ -178,6 +190,12 @@ git commit -m "Update Clippy" # Open a PR in rust-lang/rust ``` +[rustup_component_history]: https://rust-lang.github.io/rustup-components-history +[toolstate_commit_history]: https://github.com/rust-lang-nursery/rust-toolstate/commits/master +[toolstate_commit]: https://github.com/rust-lang-nursery/rust-toolstate/commit/aad74d8294e198a7cf8ac81a91aebb7f3bbcf727 +[rtim]: https://github.com/kennytm/rustup-toolchain-install-master +[`rust-lang/rust`]: https://github.com/rust-lang/rust + ## Issue and PR triage Clippy is following the [Rust triage procedure][triage] for issues and pull @@ -202,34 +220,22 @@ You can find the Clippy bors queue [here][homu_queue]. If you have @bors permissions, you can find an overview of the available commands [here][homu_instructions]. +[triage]: https://forge.rust-lang.org/triage-procedure.html +[l-crash]: https://github.com/rust-lang/rust-clippy/labels/L-crash%20%3Aboom%3A +[l-bug]: https://github.com/rust-lang/rust-clippy/labels/L-bug%20%3Abeetle%3A +[homu]: https://github.com/rust-lang/homu +[homu_instructions]: https://buildbot2.rust-lang.org/homu/ +[homu_queue]: https://buildbot2.rust-lang.org/homu/queue/clippy + ## Contributions Contributions to Clippy should be made in the form of GitHub pull requests. Each pull request will be reviewed by a core contributor (someone with permission to land patches) and either landed in the main tree or given feedback for changes that would be required. -All code in this repository is under the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0) -or the [MIT](https://opensource.org/licenses/MIT) license. +All code in this repository is under the [Apache-2.0] or the [MIT] license. -[lint_crate_entry]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/lib.rs -[else_if_without_else]: https://github.com/rust-lang/rust-clippy/blob/4253aa7137cb7378acc96133c787e49a345c2b3c/clippy_lints/src/else_if_without_else.rs -[reg_early_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_early_pass -[reg_late_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_late_pass -[early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html -[late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html -[toolstate_commit_history]: https://github.com/rust-lang-nursery/rust-toolstate/commits/master -[toolstate_commit]: https://github.com/rust-lang-nursery/rust-toolstate/commit/aad74d8294e198a7cf8ac81a91aebb7f3bbcf727 -[rtim]: https://github.com/kennytm/rustup-toolchain-install-master -[rustup_component_history]: https://rust-lang.github.io/rustup-components-history -[clippy_rfc]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md -[rfc_stability]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#stability-guarantees -[rfc_lint_cats]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#lint-audit-and-categories -[triage]: https://forge.rust-lang.org/triage-procedure.html -[l-crash]: https://github.com/rust-lang/rust-clippy/labels/L-crash%20%3Aboom%3A -[l-bug]: https://github.com/rust-lang/rust-clippy/labels/L-bug%20%3Abeetle%3A -[homu]: https://github.com/rust-lang/homu -[homu_instructions]: https://buildbot2.rust-lang.org/homu/ -[homu_queue]: https://buildbot2.rust-lang.org/homu/queue/clippy -[`rust-lang/rust`]: https://github.com/rust-lang/rust +[Apache-2.0]: https://www.apache.org/licenses/LICENSE-2.0 +[MIT]: https://opensource.org/licenses/MIT From 0de71b0e3acaed1042fb173262916644111463c5 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 11 Mar 2020 05:55:25 +0900 Subject: [PATCH 201/243] Move links to the end of each chapter on adding_lints --- doc/adding_lints.md | 67 ++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/doc/adding_lints.md b/doc/adding_lints.md index 54034f664834..1d78a27820a6 100644 --- a/doc/adding_lints.md +++ b/doc/adding_lints.md @@ -107,13 +107,15 @@ our lint, we need to commit the generated `.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. +additionally run [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 the tests. +[rustfix]: https://github.com/rust-lang/rustfix + ## Edition 2018 tests Some features require the 2018 edition to work (e.g. `async_await`), but @@ -167,10 +169,10 @@ declare_clippy_lint! { * The section of lines prefixed with `///` constitutes the lint documentation section. This is the default documentation style and will be displayed [like this][example_lint_page]. -* `FOO_FUNCTIONS` is the name of our lint. Be sure to follow the [lint naming - guidelines][lint_naming] here when naming your lint. In short, the name should - state the thing that is being checked for and read well when used with - `allow`/`warn`/`deny`. +* `FOO_FUNCTIONS` is the name of our lint. Be sure to follow the + [lint naming guidelines][lint_naming] here when naming your lint. + In short, the name should state the thing that is being checked for and + read well when used with `allow`/`warn`/`deny`. * `pedantic` sets the lint level to `Allow`. The exact mapping can be found [here][category_level_mapping] * The last part should be a text that explains what exactly is wrong with the @@ -200,7 +202,10 @@ automate everything. We will have to register our lint pass manually in the store.register_early_pass(|| box foo_functions::FooFunctions); ``` -[example lint page]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure +[declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L60 +[example_lint_page]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure +[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints +[category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L110 ## Lint passes @@ -220,6 +225,9 @@ Since we don't need type information for checking the function name, we used `--pass=early` when running the new lint automation and all the imports were added accordingly. +[early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html +[late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html + ## Emitting a lint With UI tests and the lint declaration in place, we can start working on the @@ -265,13 +273,16 @@ impl EarlyLintPass for FooFunctions { Running our UI test should now produce output that contains the lint message. +[check_fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html#method.check_fn +[diagnostics]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/utils/diagnostics.rs + ## Adding the lint logic Writing the logic for your lint will most likely be different from our example, so this section is kept rather short. Using the [`check_fn`][check_fn] method gives us access to [`FnKind`][fn_kind] -that has the `FnKind::Fn` variant. It provides access to the name of the +that has the [`FnKind::Fn`] variant. It provides access to the name of the function/method via an [`Ident`][ident]. With that we can expand our `check_fn` method to: @@ -323,6 +334,10 @@ implementation is not violating any Clippy lints itself. That should be it for the lint implementation. Running `cargo test` should now pass. +[fn_kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/visit/enum.FnKind.html +[`FnKind::Fn`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/visit/enum.FnKind.html#variant.Fn +[ident]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Ident.html + ## Author lint If you have trouble implementing your lint, there is also the internal `author` @@ -340,6 +355,8 @@ see the generated code in the output below. If the command was executed successfully, you can copy the code over to where you are implementing your lint. +[author_example]: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=9a12cb60e5c6ad4e3003ac6d5e63cf55 + ## Documentation The final thing before submitting our PR is to add some documentation to our @@ -373,11 +390,13 @@ declare_clippy_lint! { Once your lint is merged, this documentation will show up in the [lint list][lint_list]. +[lint_list]: https://rust-lang.github.io/rust-clippy/master/index.html + ## Running rustfmt -[Rustfmt](https://github.com/rust-lang/rustfmt) is a tool for formatting Rust -code according to style guidelines. Your code has to be formatted by `rustfmt` -before a PR can be merged. Clippy uses nightly `rustfmt` in the CI. +[Rustfmt] is a tool for formatting Rust code according to style guidelines. +Your code has to be formatted by `rustfmt` before a PR can be merged. +Clippy uses nightly `rustfmt` in the CI. It can be installed via `rustup`: @@ -388,12 +407,16 @@ rustup component add rustfmt --toolchain=nightly Use `cargo dev fmt` to format the whole codebase. Make sure that `rustfmt` is installed for the nightly toolchain. +[Rustfmt]: https://github.com/rust-lang/rustfmt + ## Debugging If you want to debug parts of your lint implementation, you can use the [`dbg!`] macro anywhere in your code. Running the tests should then include the debug output in the `stdout` part. +[`dbg!`]: https://doc.rust-lang.org/std/macro.dbg.html + ## PR Checklist Before submitting your PR make sure you followed all of the basic requirements: @@ -437,26 +460,14 @@ documentation currently. This is unfortunate, but in most cases you can probably get away with copying things from existing similar lints. If you are stuck, don't hesitate to ask on [Discord] or in the issue/PR. -[lint_list]: https://rust-lang.github.io/rust-clippy/master/index.html -[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints -[category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/bd23cb89ec0ea63403a17d3fc5e50c88e38dd54f/clippy_lints/src/lib.rs#L43 -[declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/a71acac1da7eaf667ab90a1d65d10e5cc4b80191/clippy_lints/src/lib.rs#L39 -[check_fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html#method.check_fn -[early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html -[late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html -[fn_kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/visit/enum.FnKind.html -[diagnostics]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/utils/diagnostics.rs [utils]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/utils/mod.rs -[ident]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Ident.html -[span]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html -[applicability]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/enum.Applicability.html [if_chain]: https://docs.rs/if_chain/*/if_chain/ -[ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/sty/index.html -[ast]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/index.html [from_expansion]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html#method.from_expansion [in_external_macro]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/fn.in_external_macro.html -[author_example]: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=9a12cb60e5c6ad4e3003ac6d5e63cf55 +[span]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html +[applicability]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/enum.Applicability.html [rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/ [nightly_docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ +[ast]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/index.html +[ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/sty/index.html [Discord]: https://discord.gg/rust-lang -[`dbg`!]: https://doc.rust-lang.org/std/macro.dbg.html From d5c8b783b8ceb0f739e307670a4f3a92ba8fdfcc Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 10 Mar 2020 14:30:07 -0700 Subject: [PATCH 202/243] Update tests/ui/needless_doc_main.rs Co-Authored-By: Philipp Krones --- tests/ui/needless_doc_main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/needless_doc_main.rs b/tests/ui/needless_doc_main.rs index 418d11eb3ee1..682d7b3c4ceb 100644 --- a/tests/ui/needless_doc_main.rs +++ b/tests/ui/needless_doc_main.rs @@ -51,7 +51,7 @@ fn bad_doctests() {} /// } /// ``` /// -/// We should not lint non-rust examples: +/// We should not lint ignored examples: /// /// ```rust,ignore /// fn main() { From 515847dad187c62701d77a9c368abe2d20e1d696 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 11 Mar 2020 06:35:07 +0900 Subject: [PATCH 203/243] Use `edition:2018` flag more widely --- tests/ui/doc_errors.rs | 2 +- tests/ui/issue_4266.rs | 2 +- tests/ui/macro_use_imports.rs | 2 +- tests/ui/methods.rs | 2 +- tests/ui/single_component_path_imports.fixed | 2 +- tests/ui/single_component_path_imports.rs | 2 +- tests/ui/use_self.fixed | 2 +- tests/ui/use_self.rs | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/ui/doc_errors.rs b/tests/ui/doc_errors.rs index 1401a658e037..445fc8d31d77 100644 --- a/tests/ui/doc_errors.rs +++ b/tests/ui/doc_errors.rs @@ -1,4 +1,4 @@ -// compile-flags: --edition 2018 +// edition:2018 #![warn(clippy::missing_errors_doc)] use std::io; diff --git a/tests/ui/issue_4266.rs b/tests/ui/issue_4266.rs index 1538abb1d776..8a9d5a3d1d56 100644 --- a/tests/ui/issue_4266.rs +++ b/tests/ui/issue_4266.rs @@ -1,4 +1,4 @@ -// compile-flags: --edition 2018 +// edition:2018 #![allow(dead_code)] async fn sink1<'a>(_: &'a str) {} // lint diff --git a/tests/ui/macro_use_imports.rs b/tests/ui/macro_use_imports.rs index 094dce17d4b6..60c64ee8146e 100644 --- a/tests/ui/macro_use_imports.rs +++ b/tests/ui/macro_use_imports.rs @@ -1,4 +1,4 @@ -// compile-flags: --edition 2018 +// edition:2018 #![warn(clippy::macro_use_imports)] use std::collections::HashMap; diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index bc4484358297..2af33b263405 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -1,5 +1,5 @@ // aux-build:option_helpers.rs -// compile-flags: --edition 2018 +// edition:2018 #![warn(clippy::all, clippy::pedantic)] #![allow( diff --git a/tests/ui/single_component_path_imports.fixed b/tests/ui/single_component_path_imports.fixed index 9095069b0939..a7a8499b58f0 100644 --- a/tests/ui/single_component_path_imports.fixed +++ b/tests/ui/single_component_path_imports.fixed @@ -1,5 +1,5 @@ // run-rustfix -// compile-flags: --edition 2018 +// edition:2018 #![warn(clippy::single_component_path_imports)] #![allow(unused_imports)] diff --git a/tests/ui/single_component_path_imports.rs b/tests/ui/single_component_path_imports.rs index 1ebb3ee59b8b..9a427e90ad3d 100644 --- a/tests/ui/single_component_path_imports.rs +++ b/tests/ui/single_component_path_imports.rs @@ -1,5 +1,5 @@ // run-rustfix -// compile-flags: --edition 2018 +// edition:2018 #![warn(clippy::single_component_path_imports)] #![allow(unused_imports)] diff --git a/tests/ui/use_self.fixed b/tests/ui/use_self.fixed index 802de31b783f..ebb3aa28daf3 100644 --- a/tests/ui/use_self.fixed +++ b/tests/ui/use_self.fixed @@ -1,5 +1,5 @@ // run-rustfix -// compile-flags: --edition 2018 +// edition:2018 #![warn(clippy::use_self)] #![allow(dead_code)] diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 605c4f8c41fd..8a182192ab34 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -1,5 +1,5 @@ // run-rustfix -// compile-flags: --edition 2018 +// edition:2018 #![warn(clippy::use_self)] #![allow(dead_code)] From d4eb4968560456827e71cdf1a48b5a4585168ec5 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 11 Mar 2020 06:35:46 +0900 Subject: [PATCH 204/243] Improve documentation --- CONTRIBUTING.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b52266ac4f1b..b1f9be44b73d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -54,7 +54,8 @@ and resolved paths. [`T-AST`] issues will generally need you to match against a predefined syntax structure. To figure out how this syntax structure is encoded in the AST, it is recommended to run `rustc -Z ast-json` on an example of the structure and compare with the [nodes in the AST docs]. -Usually the lint will end up to be a nested series of matches and ifs, [like so]. +Usually the lint will end up to be a nested series of matches and ifs, [like so][deep-nesting]. +But we can make it nest-less by using [if_chain] macro, [like this][nest-less]. [`E-medium`] issues are generally pretty easy too, though it's recommended you work on an E-easy issue first. They are mostly classified as [`E-medium`], since they might be somewhat involved code wise, @@ -71,7 +72,9 @@ an AST expression). `match_def_path()` in Clippy's `utils` module can also be us [`E-medium`]: https://github.com/rust-lang/rust-clippy/labels/E-medium [`ty`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty [nodes in the AST docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/ -[like so]: https://github.com/rust-lang/rust-clippy/blob/de5ccdfab68a5e37689f3c950ed1532ba9d652a0/src/misc.rs#L34 +[deep-nesting]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/mem_forget.rs#L29-L43 +[if_chain]: https://docs.rs/if_chain/*/if_chain +[nest-less]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/bit_mask.rs#L124-L150 ## Writing code From a4ba1027fc581379e55dce66d0b7e21d8d91dfa0 Mon Sep 17 00:00:00 2001 From: Jacob Meyers Date: Tue, 10 Mar 2020 05:41:24 -0400 Subject: [PATCH 205/243] add CR feedback --- clippy_lints/src/verbose_file_reads.rs | 25 +++++++++++++------------ tests/ui/verbose_file_reads.rs | 4 +--- tests/ui/verbose_file_reads.stderr | 12 ++++++------ 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/verbose_file_reads.rs b/clippy_lints/src/verbose_file_reads.rs index 93256790211a..37885317c58e 100644 --- a/clippy_lints/src/verbose_file_reads.rs +++ b/clippy_lints/src/verbose_file_reads.rs @@ -8,19 +8,22 @@ declare_clippy_lint! { /// **What it does:** Checks for use of File::read_to_end and File::read_to_string. /// /// **Why is this bad?** `fs::{read, read_to_string}` provide the same functionality when `buf` is empty with fewer imports and no intermediate values. - /// + /// See also: [fs::read docs](https://doc.rust-lang.org/std/fs/fn.read.html), [fs::read_to_string docs](https://doc.rust-lang.org/std/fs/fn.read_to_string.html) /// **Known problems:** None. /// /// **Example:** /// - /// ```rust, ignore - /// let mut f = File::open("foo.txt")?; + /// ```rust,no_run + /// # use std::io::Read; + /// # use std::fs::File; + /// let mut f = File::open("foo.txt").unwrap(); /// let mut bytes = Vec::new(); - /// f.read_to_end(&mut bytes)?; + /// f.read_to_end(&mut bytes).unwrap(); /// ``` /// Can be written more concisely as - /// ```rust, ignore - /// let mut bytes = fs::read("foo.txt")?; + /// ```rust,no_run + /// # use std::fs; + /// let mut bytes = fs::read("foo.txt").unwrap(); /// ``` pub VERBOSE_FILE_READS, complexity, @@ -36,19 +39,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VerboseFileReads { cx, VERBOSE_FILE_READS, expr.span, - "use of File::read_to_end", - "consider using fs::read instead", + "use of `File::read_to_end`", + "consider using `fs::read` instead", ); } else if is_file_read_to_string(cx, expr) { span_lint_and_help( cx, VERBOSE_FILE_READS, expr.span, - "use of File::read_to_string", - "consider using fs::read_to_string instead", + "use of `File::read_to_string`", + "consider using `fs::read_to_string` instead", ) - } else { - // Don't care } } } diff --git a/tests/ui/verbose_file_reads.rs b/tests/ui/verbose_file_reads.rs index 3c7c4be84b0c..e0065e05ade6 100644 --- a/tests/ui/verbose_file_reads.rs +++ b/tests/ui/verbose_file_reads.rs @@ -12,9 +12,7 @@ impl Struct { } fn main() -> std::io::Result<()> { - let mut path = temp_dir(); - path.push("test.txt"); - let file = File::create(&path)?; + let path = "foo.txt"; // Lint shouldn't catch this let s = Struct; s.read_to_end(); diff --git a/tests/ui/verbose_file_reads.stderr b/tests/ui/verbose_file_reads.stderr index 73dc22fd4dbc..550b6ab679f1 100644 --- a/tests/ui/verbose_file_reads.stderr +++ b/tests/ui/verbose_file_reads.stderr @@ -1,19 +1,19 @@ -error: use of File::read_to_end - --> $DIR/verbose_file_reads.rs:25:5 +error: use of `File::read_to_end` + --> $DIR/verbose_file_reads.rs:23:5 | LL | f.read_to_end(&mut buffer)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::verbose-file-reads` implied by `-D warnings` - = help: consider using fs::read instead + = help: consider using `fs::read` instead -error: use of File::read_to_string - --> $DIR/verbose_file_reads.rs:28:5 +error: use of `File::read_to_string` + --> $DIR/verbose_file_reads.rs:26:5 | LL | f.read_to_string(&mut string_buffer)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: consider using fs::read_to_string instead + = help: consider using `fs::read_to_string` instead error: aborting due to 2 previous errors From 9de642190eef4e9c0cb9aac8195d602ca514952d Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 13 Mar 2020 00:31:09 +0900 Subject: [PATCH 206/243] Extend `redundant_clone` to the case that cloned value is not consumed --- clippy_lints/src/redundant_clone.rs | 95 ++++++++++++++++------------- tests/ui/format.fixed | 2 +- tests/ui/format.rs | 2 +- tests/ui/redundant_clone.fixed | 10 +++ tests/ui/redundant_clone.rs | 10 +++ tests/ui/redundant_clone.stderr | 30 ++++++--- 6 files changed, 96 insertions(+), 53 deletions(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 103c063aef4b..b30d29116cc7 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -6,7 +6,7 @@ use if_chain::if_chain; use matches::matches; use rustc::mir::{ self, traversal, - visit::{MutatingUseContext, PlaceContext, Visitor as _}, + visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor as _}, }; use rustc::ty::{self, fold::TypeVisitor, Ty}; use rustc_data_structures::{fx::FxHashMap, transitive_relation::TransitiveRelation}; @@ -110,7 +110,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { continue; } - let (fn_def_id, arg, arg_ty, _) = unwrap_or_continue!(is_call_with_ref_arg(cx, mir, &terminator.kind)); + let (fn_def_id, arg, arg_ty, clone_ret) = + unwrap_or_continue!(is_call_with_ref_arg(cx, mir, &terminator.kind)); let from_borrow = match_def_path(cx, fn_def_id, &paths::CLONE_TRAIT_METHOD) || match_def_path(cx, fn_def_id, &paths::TO_OWNED_METHOD) @@ -132,8 +133,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { statement_index: bbdata.statements.len(), }; - // Cloned local - let local = if from_borrow { + // `Local` to be cloned, and a local of `clone` call's destination + let (local, ret_local) = if from_borrow { // `res = clone(arg)` can be turned into `res = move arg;` // if `arg` is the only borrow of `cloned` at this point. @@ -141,7 +142,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { continue; } - cloned + (cloned, clone_ret) } else { // `arg` is a reference as it is `.deref()`ed in the previous block. // Look into the predecessor block and find out the source of deref. @@ -153,15 +154,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { let pred_terminator = mir[ps[0]].terminator(); // receiver of the `deref()` call - let pred_arg = if_chain! { - if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, Some(res))) = + let (pred_arg, deref_clone_ret) = if_chain! { + if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, res)) = is_call_with_ref_arg(cx, mir, &pred_terminator.kind); - if res.local == cloned; + if res == cloned; if match_def_path(cx, pred_fn_def_id, &paths::DEREF_TRAIT_METHOD); if match_type(cx, pred_arg_ty, &paths::PATH_BUF) || match_type(cx, pred_arg_ty, &paths::OS_STRING); then { - pred_arg + (pred_arg, res) } else { continue; } @@ -188,25 +189,32 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { continue; } - local + (local, deref_clone_ret) }; - // `local` cannot be moved out if it is used later - let used_later = traversal::ReversePostorder::new(&mir, bb).skip(1).any(|(tbb, tdata)| { - // Give up on loops - if tdata.terminator().successors().any(|s| *s == bb) { - return true; - } + // 1. `local` cannot be moved out if it is used later. + // 2. If `ret_local` is not consumed, we can remove this `clone` call anyway. + let (used, consumed) = traversal::ReversePostorder::new(&mir, bb).skip(1).fold( + (false, false), + |(used, consumed), (tbb, tdata)| { + // Short-circuit + if (used && consumed) || + // Give up on loops + tdata.terminator().successors().any(|s| *s == bb) + { + return (true, true); + } - let mut vis = LocalUseVisitor { - local, - used_other_than_drop: false, - }; - vis.visit_basic_block_data(tbb, tdata); - vis.used_other_than_drop - }); + let mut vis = LocalUseVisitor { + used: (local, false), + consumed: (ret_local, false), + }; + vis.visit_basic_block_data(tbb, tdata); + (used || vis.used.1, consumed || vis.consumed.1) + }, + ); - if !used_later { + if !used || !consumed { let span = terminator.source_info.span; let scope = terminator.source_info.scope; let node = mir.source_scopes[scope] @@ -240,10 +248,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { String::new(), app, ); - db.span_note( - span.with_hi(span.lo() + BytePos(u32::try_from(dot).unwrap())), - "this value is dropped without further use", - ); + if used { + db.span_note( + span, + "cloned value is not consumed", + ); + } else { + db.span_note( + span.with_hi(span.lo() + BytePos(u32::try_from(dot).unwrap())), + "this value is dropped without further use", + ); + } }); } else { span_lint_hir(cx, REDUNDANT_CLONE, node, span, "redundant clone"); @@ -259,7 +274,7 @@ fn is_call_with_ref_arg<'tcx>( cx: &LateContext<'_, 'tcx>, mir: &'tcx mir::Body<'tcx>, kind: &'tcx mir::TerminatorKind<'tcx>, -) -> Option<(def_id::DefId, mir::Local, Ty<'tcx>, Option<&'tcx mir::Place<'tcx>>)> { +) -> Option<(def_id::DefId, mir::Local, Ty<'tcx>, mir::Local)> { if_chain! { if let mir::TerminatorKind::Call { func, args, destination, .. } = kind; if args.len() == 1; @@ -268,7 +283,7 @@ fn is_call_with_ref_arg<'tcx>( if let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(&*mir, cx.tcx)); if !is_copy(cx, inner_ty); then { - Some((def_id, *local, inner_ty, destination.as_ref().map(|(dest, _)| dest))) + Some((def_id, *local, inner_ty, destination.as_ref().map(|(dest, _)| dest)?.as_local()?)) } else { None } @@ -337,8 +352,8 @@ fn base_local_and_movability<'tcx>( } struct LocalUseVisitor { - local: mir::Local, - used_other_than_drop: bool, + used: (mir::Local, bool), + consumed: (mir::Local, bool), } impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor { @@ -346,11 +361,6 @@ impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor { let statements = &data.statements; for (statement_index, statement) in statements.iter().enumerate() { self.visit_statement(statement, mir::Location { block, statement_index }); - - // Once flagged, skip remaining statements - if self.used_other_than_drop { - return; - } } self.visit_terminator( @@ -363,13 +373,14 @@ impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor { } fn visit_local(&mut self, local: &mir::Local, ctx: PlaceContext, _: mir::Location) { - match ctx { - PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(_) => return, - _ => {}, + if *local == self.used.0 + && !matches!(ctx, PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(_)) + { + self.used.1 = true; } - if *local == self.local { - self.used_other_than_drop = true; + if *local == self.consumed.0 && matches!(ctx, PlaceContext::NonMutatingUse(NonMutatingUseContext::Move)) { + self.consumed.1 = true; } } } diff --git a/tests/ui/format.fixed b/tests/ui/format.fixed index 6e100230a3ad..306514769990 100644 --- a/tests/ui/format.fixed +++ b/tests/ui/format.fixed @@ -1,6 +1,6 @@ // run-rustfix -#![allow(clippy::print_literal)] +#![allow(clippy::print_literal, clippy::redundant_clone)] #![warn(clippy::useless_format)] struct Foo(pub String); diff --git a/tests/ui/format.rs b/tests/ui/format.rs index 1fae6603ac09..b604d79cca37 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -1,6 +1,6 @@ // run-rustfix -#![allow(clippy::print_literal)] +#![allow(clippy::print_literal, clippy::redundant_clone)] #![warn(clippy::useless_format)] struct Foo(pub String); diff --git a/tests/ui/redundant_clone.fixed b/tests/ui/redundant_clone.fixed index 84931f66fa8d..99d97f9cc3ce 100644 --- a/tests/ui/redundant_clone.fixed +++ b/tests/ui/redundant_clone.fixed @@ -50,6 +50,7 @@ fn main() { cannot_double_move(Alpha); cannot_move_from_type_with_drop(); borrower_propagation(); + not_consumed(); } #[derive(Clone)] @@ -136,3 +137,12 @@ fn borrower_propagation() { let _f = f.clone(); // ok } } + +fn not_consumed() { + let x = std::path::PathBuf::from("home"); + let y = x.join("matthias"); + // join() creates a new owned PathBuf, does not take a &mut to x variable, thus the .clone() is + // redundant. (It also does not consume the PathBuf) + + println!("x: {:?}, y: {:?}", x, y); +} diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs index 9ea2de9a3daa..58cd05c67cf0 100644 --- a/tests/ui/redundant_clone.rs +++ b/tests/ui/redundant_clone.rs @@ -50,6 +50,7 @@ fn main() { cannot_double_move(Alpha); cannot_move_from_type_with_drop(); borrower_propagation(); + not_consumed(); } #[derive(Clone)] @@ -136,3 +137,12 @@ fn borrower_propagation() { let _f = f.clone(); // ok } } + +fn not_consumed() { + let x = std::path::PathBuf::from("home"); + let y = x.clone().join("matthias"); + // join() creates a new owned PathBuf, does not take a &mut to x variable, thus the .clone() is + // redundant. (It also does not consume the PathBuf) + + println!("x: {:?}, y: {:?}", x, y); +} diff --git a/tests/ui/redundant_clone.stderr b/tests/ui/redundant_clone.stderr index 0f185cda0197..04fe74e9175b 100644 --- a/tests/ui/redundant_clone.stderr +++ b/tests/ui/redundant_clone.stderr @@ -108,52 +108,64 @@ LL | let _t = tup.0.clone(); | ^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:59:22 + --> $DIR/redundant_clone.rs:60:22 | LL | (a.clone(), a.clone()) | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:59:21 + --> $DIR/redundant_clone.rs:60:21 | LL | (a.clone(), a.clone()) | ^ error: redundant clone - --> $DIR/redundant_clone.rs:119:15 + --> $DIR/redundant_clone.rs:120:15 | LL | let _s = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:119:14 + --> $DIR/redundant_clone.rs:120:14 | LL | let _s = s.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:120:15 + --> $DIR/redundant_clone.rs:121:15 | LL | let _t = t.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:120:14 + --> $DIR/redundant_clone.rs:121:14 | LL | let _t = t.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:130:19 + --> $DIR/redundant_clone.rs:131:19 | LL | let _f = f.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:130:18 + --> $DIR/redundant_clone.rs:131:18 | LL | let _f = f.clone(); | ^ -error: aborting due to 13 previous errors +error: redundant clone + --> $DIR/redundant_clone.rs:143:14 + | +LL | let y = x.clone().join("matthias"); + | ^^^^^^^^ help: remove this + | +note: cloned value is not consumed + --> $DIR/redundant_clone.rs:143:13 + | +LL | let y = x.clone().join("matthias"); + | ^^^^^^^^^ + +error: aborting due to 14 previous errors From a3773785288e71fde264b9264a142a662aace5ee Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 13 Mar 2020 00:54:40 +0900 Subject: [PATCH 207/243] Only fires on temporaries `let y = x.clone()` cannot be turned into `let y = x` without moving x, regardless of whether `y` is consumed or not. --- clippy_lints/src/redundant_clone.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index b30d29116cc7..7c1a70408465 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -192,10 +192,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { (local, deref_clone_ret) }; - // 1. `local` cannot be moved out if it is used later. - // 2. If `ret_local` is not consumed, we can remove this `clone` call anyway. + let is_temp = mir_read_only.local_kind(ret_local) == mir::LocalKind::Temp; + + // 1. `local` can be moved out if it is not used later. + // 2. If `ret_local` is a temporary and is not consumed, we can remove this `clone` call anyway. let (used, consumed) = traversal::ReversePostorder::new(&mir, bb).skip(1).fold( - (false, false), + (false, !is_temp), |(used, consumed), (tbb, tdata)| { // Short-circuit if (used && consumed) || From aca64b8df77670c6661b7174d7edc16133442162 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 13 Mar 2020 01:25:18 +0900 Subject: [PATCH 208/243] Check for mutation --- clippy_lints/src/redundant_clone.rs | 25 ++++++++++++++++--------- tests/ui/redundant_clone.fixed | 5 +++++ tests/ui/redundant_clone.rs | 5 +++++ tests/ui/redundant_clone.stderr | 2 +- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 7c1a70408465..624fe227ca3d 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -195,8 +195,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { let is_temp = mir_read_only.local_kind(ret_local) == mir::LocalKind::Temp; // 1. `local` can be moved out if it is not used later. - // 2. If `ret_local` is a temporary and is not consumed, we can remove this `clone` call anyway. - let (used, consumed) = traversal::ReversePostorder::new(&mir, bb).skip(1).fold( + // 2. If `ret_local` is a temporary and is neither consumed nor mutated, we can remove this `clone` + // call anyway. + let (used, consumed_or_mutated) = traversal::ReversePostorder::new(&mir, bb).skip(1).fold( (false, !is_temp), |(used, consumed), (tbb, tdata)| { // Short-circuit @@ -209,14 +210,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { let mut vis = LocalUseVisitor { used: (local, false), - consumed: (ret_local, false), + consumed_or_mutated: (ret_local, false), }; vis.visit_basic_block_data(tbb, tdata); - (used || vis.used.1, consumed || vis.consumed.1) + (used || vis.used.1, consumed || vis.consumed_or_mutated.1) }, ); - if !used || !consumed { + if !used || !consumed_or_mutated { let span = terminator.source_info.span; let scope = terminator.source_info.scope; let node = mir.source_scopes[scope] @@ -253,7 +254,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { if used { db.span_note( span, - "cloned value is not consumed", + "cloned value is neither consumed nor mutated", ); } else { db.span_note( @@ -355,7 +356,7 @@ fn base_local_and_movability<'tcx>( struct LocalUseVisitor { used: (mir::Local, bool), - consumed: (mir::Local, bool), + consumed_or_mutated: (mir::Local, bool), } impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor { @@ -381,8 +382,14 @@ impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor { self.used.1 = true; } - if *local == self.consumed.0 && matches!(ctx, PlaceContext::NonMutatingUse(NonMutatingUseContext::Move)) { - self.consumed.1 = true; + if *local == self.consumed_or_mutated.0 { + match ctx { + PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) + | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => { + self.consumed_or_mutated.1 = true; + }, + _ => {}, + } } } } diff --git a/tests/ui/redundant_clone.fixed b/tests/ui/redundant_clone.fixed index 99d97f9cc3ce..17734b04aba4 100644 --- a/tests/ui/redundant_clone.fixed +++ b/tests/ui/redundant_clone.fixed @@ -145,4 +145,9 @@ fn not_consumed() { // redundant. (It also does not consume the PathBuf) println!("x: {:?}, y: {:?}", x, y); + + let mut s = String::new(); + s.clone().push_str("foo"); // OK, removing this `clone()` will change the behavior. + s.push_str("bar"); + assert_eq!(s, "bar"); } diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs index 58cd05c67cf0..aee6855eea94 100644 --- a/tests/ui/redundant_clone.rs +++ b/tests/ui/redundant_clone.rs @@ -145,4 +145,9 @@ fn not_consumed() { // redundant. (It also does not consume the PathBuf) println!("x: {:?}, y: {:?}", x, y); + + let mut s = String::new(); + s.clone().push_str("foo"); // OK, removing this `clone()` will change the behavior. + s.push_str("bar"); + assert_eq!(s, "bar"); } diff --git a/tests/ui/redundant_clone.stderr b/tests/ui/redundant_clone.stderr index 04fe74e9175b..9c27812b9cdc 100644 --- a/tests/ui/redundant_clone.stderr +++ b/tests/ui/redundant_clone.stderr @@ -161,7 +161,7 @@ error: redundant clone LL | let y = x.clone().join("matthias"); | ^^^^^^^^ help: remove this | -note: cloned value is not consumed +note: cloned value is neither consumed nor mutated --> $DIR/redundant_clone.rs:143:13 | LL | let y = x.clone().join("matthias"); From d9ad33852c1e0179fc9b22ac2324ab18455879f1 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 13 Mar 2020 02:06:47 +0900 Subject: [PATCH 209/243] Use visit_place --- clippy_lints/src/redundant_clone.rs | 8 +++++--- tests/ui/redundant_clone.fixed | 9 +++++++++ tests/ui/redundant_clone.rs | 9 +++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 624fe227ca3d..b63bb371c4f3 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -375,14 +375,16 @@ impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor { ); } - fn visit_local(&mut self, local: &mir::Local, ctx: PlaceContext, _: mir::Location) { - if *local == self.used.0 + fn visit_place(&mut self, place: &mir::Place<'tcx>, ctx: PlaceContext, _: mir::Location) { + let local = place.local; + + if local == self.used.0 && !matches!(ctx, PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(_)) { self.used.1 = true; } - if *local == self.consumed_or_mutated.0 { + if local == self.consumed_or_mutated.0 { match ctx { PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => { diff --git a/tests/ui/redundant_clone.fixed b/tests/ui/redundant_clone.fixed index 17734b04aba4..54815603c6de 100644 --- a/tests/ui/redundant_clone.fixed +++ b/tests/ui/redundant_clone.fixed @@ -150,4 +150,13 @@ fn not_consumed() { s.clone().push_str("foo"); // OK, removing this `clone()` will change the behavior. s.push_str("bar"); assert_eq!(s, "bar"); + + let t = Some(s); + // OK + if let Some(x) = t.clone() { + println!("{}", x); + } + if let Some(x) = t { + println!("{}", x); + } } diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs index aee6855eea94..a9b31183adc8 100644 --- a/tests/ui/redundant_clone.rs +++ b/tests/ui/redundant_clone.rs @@ -150,4 +150,13 @@ fn not_consumed() { s.clone().push_str("foo"); // OK, removing this `clone()` will change the behavior. s.push_str("bar"); assert_eq!(s, "bar"); + + let t = Some(s); + // OK + if let Some(x) = t.clone() { + println!("{}", x); + } + if let Some(x) = t { + println!("{}", x); + } } From 3e3776666ea4dbf92e4450f5753a0a45827b349e Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 13 Mar 2020 04:56:55 +0900 Subject: [PATCH 210/243] Rustup to rust-lang/rust#69674 --- clippy_lints/src/attrs.rs | 4 ++-- clippy_lints/src/doc.rs | 2 +- clippy_lints/src/functions.rs | 2 +- clippy_lints/src/inline_fn_without_body.rs | 2 +- clippy_lints/src/lifetimes.rs | 2 +- clippy_lints/src/methods/mod.rs | 2 +- clippy_lints/src/missing_doc.rs | 2 +- clippy_lints/src/missing_inline.rs | 2 +- clippy_lints/src/mut_key.rs | 2 +- clippy_lints/src/ptr.rs | 2 +- clippy_lints/src/trivially_copy_pass_by_ref.rs | 2 +- clippy_lints/src/types.rs | 4 ++-- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 7d5e1d881912..833739f1bd3c 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -379,8 +379,8 @@ fn is_relevant_impl(cx: &LateContext<'_, '_>, item: &ImplItem<'_>) -> bool { fn is_relevant_trait(cx: &LateContext<'_, '_>, item: &TraitItem<'_>) -> bool { match item.kind { - TraitItemKind::Method(_, TraitMethod::Required(_)) => true, - TraitItemKind::Method(_, TraitMethod::Provided(eid)) => { + TraitItemKind::Fn(_, TraitMethod::Required(_)) => true, + TraitItemKind::Fn(_, TraitMethod::Provided(eid)) => { is_relevant_expr(cx, cx.tcx.body_tables(eid), &cx.tcx.hir().body(eid).value) }, _ => false, diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 754d38f40158..006d732703ec 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -179,7 +179,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DocMarkdown { fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem<'_>) { let headers = check_attrs(cx, &self.valid_idents, &item.attrs); - if let hir::TraitItemKind::Method(ref sig, ..) = item.kind { + if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind { if !in_external_macro(cx.tcx.sess, item.span) { lint_for_missing_headers(cx, item.hir_id, item.span, sig, headers, None); } diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index e435b61bbbef..c43b2075b646 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -273,7 +273,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { } fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem<'_>) { - if let hir::TraitItemKind::Method(ref sig, ref eid) = item.kind { + if let hir::TraitItemKind::Fn(ref sig, ref eid) = item.kind { // don't lint extern functions decls, it's not their fault if sig.header.abi == Abi::Rust { self.check_arg_number(cx, &sig.decl, item.span.with_hi(sig.decl.output.span().hi())); diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index de16a4f1ef82..32032c4da885 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -32,7 +32,7 @@ declare_lint_pass!(InlineFnWithoutBody => [INLINE_FN_WITHOUT_BODY]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InlineFnWithoutBody { fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem<'_>) { - if let TraitItemKind::Method(_, TraitMethod::Required(_)) = item.kind { + if let TraitItemKind::Fn(_, TraitMethod::Required(_)) = item.kind { check_attrs(cx, item.ident.name, &item.attrs); } } diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index a120e3a7517f..3b687bd54a1c 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -100,7 +100,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Lifetimes { } fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem<'_>) { - if let TraitItemKind::Method(ref sig, ref body) = item.kind { + if let TraitItemKind::Fn(ref sig, ref body) = item.kind { let body = match *body { TraitMethod::Required(_) => None, TraitMethod::Provided(id) => Some(id), diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index eef510540901..19d9a31aaf41 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1738,7 +1738,7 @@ fn lint_expect_fun_call( if let hir::ExprKind::Path(ref p) = fun.kind { match cx.tables.qpath_res(p, fun.hir_id) { hir::def::Res::Def(hir::def::DefKind::Fn, def_id) - | hir::def::Res::Def(hir::def::DefKind::Method, def_id) => matches!( + | hir::def::Res::Def(hir::def::DefKind::AssocFn, def_id) => matches!( cx.tcx.fn_sig(def_id).output().skip_binder().kind, ty::Ref(ty::ReStatic, ..) ), diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 5e32172d78a1..57bec0a65b37 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -164,7 +164,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, trait_item: &'tcx hir::TraitItem<'_>) { let desc = match trait_item.kind { hir::TraitItemKind::Const(..) => "an associated constant", - hir::TraitItemKind::Method(..) => "a trait method", + hir::TraitItemKind::Fn(..) => "a trait method", hir::TraitItemKind::Type(..) => "an associated type", }; diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index b736c58879ba..fad4d6d0fe2e 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -100,7 +100,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { let tit_ = cx.tcx.hir().trait_item(tit.id); match tit_.kind { hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => {}, - hir::TraitItemKind::Method(..) => { + hir::TraitItemKind::Fn(..) => { if tit.defaultness.has_value() { // trait method with default body needs inline in case // an impl is not provided diff --git a/clippy_lints/src/mut_key.rs b/clippy_lints/src/mut_key.rs index d48c4c419aef..61f514a740a5 100644 --- a/clippy_lints/src/mut_key.rs +++ b/clippy_lints/src/mut_key.rs @@ -67,7 +67,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableKeyType { } fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem<'tcx>) { - if let hir::TraitItemKind::Method(ref sig, ..) = item.kind { + if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind { check_sig(cx, item.hir_id, &sig.decl); } } diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index c1aee94aa421..a6d62406aa76 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -121,7 +121,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ptr { } fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem<'_>) { - if let TraitItemKind::Method(ref sig, ref trait_method) = item.kind { + if let TraitItemKind::Fn(ref sig, ref trait_method) = item.kind { let body_id = if let TraitMethod::Provided(b) = *trait_method { Some(b) } else { diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index e00bc2e090ae..7e9a94f14fef 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -132,7 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef { return; } - if let hir::TraitItemKind::Method(method_sig, _) = &item.kind { + if let hir::TraitItemKind::Fn(method_sig, _) = &item.kind { self.check_poly_fn(cx, item.hir_id, &*method_sig.decl, None); } } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index e1685c97a065..fbd3f37c5643 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -204,7 +204,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Types { fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, item: &TraitItem<'_>) { match item.kind { TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => self.check_ty(cx, ty, false), - TraitItemKind::Method(ref sig, _) => self.check_fn_decl(cx, &sig.decl), + TraitItemKind::Fn(ref sig, _) => self.check_fn_decl(cx, &sig.decl), _ => (), } } @@ -1457,7 +1457,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexity { fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem<'_>) { match item.kind { TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => self.check_type(cx, ty), - TraitItemKind::Method(FnSig { ref decl, .. }, TraitMethod::Required(_)) => self.check_fndecl(cx, decl), + TraitItemKind::Fn(FnSig { ref decl, .. }, TraitMethod::Required(_)) => self.check_fndecl(cx, decl), // methods with default impl are covered by check_fn _ => (), } From da29402d2eec18c88c871ba83c417799b0798b4c Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 12 Mar 2020 21:01:19 +0100 Subject: [PATCH 211/243] Update CHANGELOG.md --- CHANGELOG.md | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32cbbe801017..9bd8b681b13b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,75 @@ document. Current Beta +[69f99e7...329923e](https://github.com/rust-lang/rust-clippy/compare/69f99e7...329923e) + +* New Lints: + * [`filetype_is_file`] [#4543](https://github.com/rust-lang/rust-clippy/pull/4543) + * [`let_underscore_must_use`] [#4823](https://github.com/rust-lang/rust-clippy/pull/4823) + * [`modulo_arithmetic`] [#4867](https://github.com/rust-lang/rust-clippy/pull/4867) + * [`mem_replace_with_default`] [#4881](https://github.com/rust-lang/rust-clippy/pull/4881) + * [`mutable_key_type`] [#4885](https://github.com/rust-lang/rust-clippy/pull/4885) + * [`imprecise_flops`] [#4897](https://github.com/rust-lang/rust-clippy/pull/4897) + * [`suboptimal_flops`] [#4897](https://github.com/rust-lang/rust-clippy/pull/4897) + * [`option_as_ref_deref`] [#4945](https://github.com/rust-lang/rust-clippy/pull/4945) + * [`wildcard_in_or_patterns`] [#4960](https://github.com/rust-lang/rust-clippy/pull/4960) + * [`iter_nth_zero`] [#4966](https://github.com/rust-lang/rust-clippy/pull/4966) + * [`invalid_atomic_ordering`] [#4999](https://github.com/rust-lang/rust-clippy/pull/4999) + * [`wildcard_imports`] [#5029](https://github.com/rust-lang/rust-clippy/pull/5029) + * [`single_component_path_imports`] [#5058](https://github.com/rust-lang/rust-clippy/pull/5058) + * [`match_single_binding`] [#5061](https://github.com/rust-lang/rust-clippy/pull/5061) + * [`skip_while_next`] [#5067](https://github.com/rust-lang/rust-clippy/pull/5067) + * [`let_underscore_lock`] [#5101](https://github.com/rust-lang/rust-clippy/pull/5101) + * [`struct_excessive_bools`] [#5125](https://github.com/rust-lang/rust-clippy/pull/5125) + * [`fn_params_excessive_bools`] [#5125](https://github.com/rust-lang/rust-clippy/pull/5125) + * [`option_env_unwrap`] [#5148](https://github.com/rust-lang/rust-clippy/pull/5148) + * [`lossy_float_literal`] [#5202](https://github.com/rust-lang/rust-clippy/pull/5202) + * [`rest_pat_in_fully_bound_structs`] [#5258](https://github.com/rust-lang/rust-clippy/pull/5258) +* Move [`transmute_float_to_int`] from nursery to complexity group + [#5015](https://github.com/rust-lang/rust-clippy/pull/5015) +* Move [`range_plus_one`] to pedantic group [#5057](https://github.com/rust-lang/rust-clippy/pull/5057) +* Move [`unneeded_field_pattern`] to pedantic group [#5200](https://github.com/rust-lang/rust-clippy/pull/5200) +* Move [`debug_assert_with_mut_call`] to nursery group [#5106](https://github.com/rust-lang/rust-clippy/pull/5106) +* Deprecate [`unused_label`] [#4930](https://github.com/rust-lang/rust-clippy/pull/4930) +* Lint vectored IO in `unused_io_amount` [#5027](https://github.com/rust-lang/rust-clippy/pull/5027) +* Make `vec_box` configurable by adding a size threshold [#5081](https://github.com/rust-lang/rust-clippy/pull/5081) +* Make `missing_errors_doc` lint also trigger an `async` functions + [#5181](https://github.com/rust-lang/rust-clippy/pull/5181) +* Add more constants to `approx_constant` [#5193](https://github.com/rust-lang/rust-clippy/pull/5193) +* Extend `question_mark` lint [#5266](https://github.com/rust-lang/rust-clippy/pull/5266) +* Also lint constants in `cmp_nan` [#4910](https://github.com/rust-lang/rust-clippy/pull/4910) +* Fix false negative in `expect_fun_call` [#4915](https://github.com/rust-lang/rust-clippy/pull/4915) +* Fix false negative in `redundant_clone` [#5017](https://github.com/rust-lang/rust-clippy/pull/5017) +* Fix false positive in `map_clone` [#4937](https://github.com/rust-lang/rust-clippy/pull/4937) +* Fix false positive in `replace_consts` [#4977](https://github.com/rust-lang/rust-clippy/pull/4977) +* Fix false positive in `let_and_return` [#5008](https://github.com/rust-lang/rust-clippy/pull/5008) +* Fix false positive in `use_debug` [#5047](https://github.com/rust-lang/rust-clippy/pull/5047) +* Fix false positive in `eq_op` [#5079](https://github.com/rust-lang/rust-clippy/pull/5079) +* Fix false positive in `possible_missing_comma` [#5083](https://github.com/rust-lang/rust-clippy/pull/5083) +* Fix false positive in `debug_assert_with_mut_call` [#5106](https://github.com/rust-lang/rust-clippy/pull/5106) +* Fix false positive in `unnecessary_unwrap` [#5132](https://github.com/rust-lang/rust-clippy/pull/5132) +* Fix false positive in `zero_prefixed_literal` [#5170](https://github.com/rust-lang/rust-clippy/pull/5170) +* Fix false positive in `missing_const_for_fn` [#5216](https://github.com/rust-lang/rust-clippy/pull/5216) +* Don't trigger `let_underscore_must_use` in external macros + [#5082](https://github.com/rust-lang/rust-clippy/pull/5082) +* Don't trigger `empty_loop` in `no_std` crates [#5086](https://github.com/rust-lang/rust-clippy/pull/5086) +* Improve suggestion for `option_map_unwrap_or` [#4634](https://github.com/rust-lang/rust-clippy/pull/4634) +* Improve suggestion for `wildcard_enum_match_arm` [#4934](https://github.com/rust-lang/rust-clippy/pull/4934) +* Improve suggestion for `cognitive_complexity` [#4935](https://github.com/rust-lang/rust-clippy/pull/4935) +* Improve suggestion for `decimal_literal_representation` [#4956](https://github.com/rust-lang/rust-clippy/pull/4956) +* Improve suggestion for `unknown_clippy_lints` [#4963](https://github.com/rust-lang/rust-clippy/pull/4963) +* Improve suggestion for `explicit_into_iter_loop` [#4978](https://github.com/rust-lang/rust-clippy/pull/4978) +* Improve suggestion for `useless_attribute` [#5022](https://github.com/rust-lang/rust-clippy/pull/5022) +* Improve suggestion for `if_let_some_result` [#5032](https://github.com/rust-lang/rust-clippy/pull/5032) +* Improve suggestion when blocks of code are suggested [#5134](https://github.com/rust-lang/rust-clippy/pull/5134) +* Fix ICE in `unsound_collection_transmute` [#4975](https://github.com/rust-lang/rust-clippy/pull/4975) +* Fix ICE in `misc_early` lints [#5129](https://github.com/rust-lang/rust-clippy/pull/5129) +* Fix ICE in `missing_errors_doc` [#5213](https://github.com/rust-lang/rust-clippy/pull/5213) +* Fix ICE when evaluating `usize`s [#5256](https://github.com/rust-lang/rust-clippy/pull/5256) +* Improve documentation of `empty_enum`, `replace_consts`, `redundant_clone`, and `iterator_step_by_zero` +* Add documentation pages for stable releases [#5171](https://github.com/rust-lang/rust-clippy/pull/5171) +* Clippy now runs completely on GitHub Actions [#5190](https://github.com/rust-lang/rust-clippy/pull/5190) + ## Rust 1.41 Current stable, released 2020-01-30 From 6525127c624d24497256ec02eed571b3978c0168 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 12 Mar 2020 21:02:08 +0100 Subject: [PATCH 212/243] Update changelog_update doc to reflect the actual ordering of the changelog --- doc/changelog_update.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/changelog_update.md b/doc/changelog_update.md index cabf25135dac..5c7898fc465f 100644 --- a/doc/changelog_update.md +++ b/doc/changelog_update.md @@ -55,10 +55,13 @@ try to keep it somewhat coherent. The order should roughly be: 1. New lints -2. Changes that expand what code existing lints cover -3. ICE fixes +2. Moves or deprecations of lints +3. Changes that expand what code existing lints cover 4. False positive fixes 5. Suggestion fixes/improvements +6. ICE fixes +7. Documentation improvements +8. Others Please also be sure to update the Beta/Unreleased sections at the top with the relevant commit ranges. From 7b08c7a36e22b4bdc573103ce327662f346b525a Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 12 Mar 2020 20:54:25 +0100 Subject: [PATCH 213/243] Change changelog formatting --- CHANGELOG.md | 131 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 77 insertions(+), 54 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bd8b681b13b..c8d41e3b31d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,72 +14,95 @@ Current Beta [69f99e7...329923e](https://github.com/rust-lang/rust-clippy/compare/69f99e7...329923e) -* New Lints: - * [`filetype_is_file`] [#4543](https://github.com/rust-lang/rust-clippy/pull/4543) - * [`let_underscore_must_use`] [#4823](https://github.com/rust-lang/rust-clippy/pull/4823) - * [`modulo_arithmetic`] [#4867](https://github.com/rust-lang/rust-clippy/pull/4867) - * [`mem_replace_with_default`] [#4881](https://github.com/rust-lang/rust-clippy/pull/4881) - * [`mutable_key_type`] [#4885](https://github.com/rust-lang/rust-clippy/pull/4885) - * [`imprecise_flops`] [#4897](https://github.com/rust-lang/rust-clippy/pull/4897) - * [`suboptimal_flops`] [#4897](https://github.com/rust-lang/rust-clippy/pull/4897) - * [`option_as_ref_deref`] [#4945](https://github.com/rust-lang/rust-clippy/pull/4945) - * [`wildcard_in_or_patterns`] [#4960](https://github.com/rust-lang/rust-clippy/pull/4960) - * [`iter_nth_zero`] [#4966](https://github.com/rust-lang/rust-clippy/pull/4966) - * [`invalid_atomic_ordering`] [#4999](https://github.com/rust-lang/rust-clippy/pull/4999) - * [`wildcard_imports`] [#5029](https://github.com/rust-lang/rust-clippy/pull/5029) - * [`single_component_path_imports`] [#5058](https://github.com/rust-lang/rust-clippy/pull/5058) - * [`match_single_binding`] [#5061](https://github.com/rust-lang/rust-clippy/pull/5061) - * [`skip_while_next`] [#5067](https://github.com/rust-lang/rust-clippy/pull/5067) - * [`let_underscore_lock`] [#5101](https://github.com/rust-lang/rust-clippy/pull/5101) - * [`struct_excessive_bools`] [#5125](https://github.com/rust-lang/rust-clippy/pull/5125) - * [`fn_params_excessive_bools`] [#5125](https://github.com/rust-lang/rust-clippy/pull/5125) - * [`option_env_unwrap`] [#5148](https://github.com/rust-lang/rust-clippy/pull/5148) - * [`lossy_float_literal`] [#5202](https://github.com/rust-lang/rust-clippy/pull/5202) - * [`rest_pat_in_fully_bound_structs`] [#5258](https://github.com/rust-lang/rust-clippy/pull/5258) +### New lints + +* [`filetype_is_file`] [#4543](https://github.com/rust-lang/rust-clippy/pull/4543) +* [`let_underscore_must_use`] [#4823](https://github.com/rust-lang/rust-clippy/pull/4823) +* [`modulo_arithmetic`] [#4867](https://github.com/rust-lang/rust-clippy/pull/4867) +* [`mem_replace_with_default`] [#4881](https://github.com/rust-lang/rust-clippy/pull/4881) +* [`mutable_key_type`] [#4885](https://github.com/rust-lang/rust-clippy/pull/4885) +* [`imprecise_flops`] [#4897](https://github.com/rust-lang/rust-clippy/pull/4897) +* [`suboptimal_flops`] [#4897](https://github.com/rust-lang/rust-clippy/pull/4897) +* [`option_as_ref_deref`] [#4945](https://github.com/rust-lang/rust-clippy/pull/4945) +* [`wildcard_in_or_patterns`] [#4960](https://github.com/rust-lang/rust-clippy/pull/4960) +* [`iter_nth_zero`] [#4966](https://github.com/rust-lang/rust-clippy/pull/4966) +* [`invalid_atomic_ordering`] [#4999](https://github.com/rust-lang/rust-clippy/pull/4999) +* [`wildcard_imports`] [#5029](https://github.com/rust-lang/rust-clippy/pull/5029) +* [`single_component_path_imports`] [#5058](https://github.com/rust-lang/rust-clippy/pull/5058) +* [`match_single_binding`] [#5061](https://github.com/rust-lang/rust-clippy/pull/5061) +* [`skip_while_next`] [#5067](https://github.com/rust-lang/rust-clippy/pull/5067) +* [`let_underscore_lock`] [#5101](https://github.com/rust-lang/rust-clippy/pull/5101) +* [`struct_excessive_bools`] [#5125](https://github.com/rust-lang/rust-clippy/pull/5125) +* [`fn_params_excessive_bools`] [#5125](https://github.com/rust-lang/rust-clippy/pull/5125) +* [`option_env_unwrap`] [#5148](https://github.com/rust-lang/rust-clippy/pull/5148) +* [`lossy_float_literal`] [#5202](https://github.com/rust-lang/rust-clippy/pull/5202) +* [`rest_pat_in_fully_bound_structs`] [#5258](https://github.com/rust-lang/rust-clippy/pull/5258) + +### Moves and Deprecations + * Move [`transmute_float_to_int`] from nursery to complexity group [#5015](https://github.com/rust-lang/rust-clippy/pull/5015) * Move [`range_plus_one`] to pedantic group [#5057](https://github.com/rust-lang/rust-clippy/pull/5057) * Move [`unneeded_field_pattern`] to pedantic group [#5200](https://github.com/rust-lang/rust-clippy/pull/5200) * Move [`debug_assert_with_mut_call`] to nursery group [#5106](https://github.com/rust-lang/rust-clippy/pull/5106) * Deprecate [`unused_label`] [#4930](https://github.com/rust-lang/rust-clippy/pull/4930) -* Lint vectored IO in `unused_io_amount` [#5027](https://github.com/rust-lang/rust-clippy/pull/5027) -* Make `vec_box` configurable by adding a size threshold [#5081](https://github.com/rust-lang/rust-clippy/pull/5081) -* Make `missing_errors_doc` lint also trigger an `async` functions + +### Enhancements + +* Lint vectored IO in [`unused_io_amount`] [#5027](https://github.com/rust-lang/rust-clippy/pull/5027) +* Make [`vec_box`] configurable by adding a size threshold [#5081](https://github.com/rust-lang/rust-clippy/pull/5081) +* Make [`missing_errors_doc`] lint also trigger an `async` functions [#5181](https://github.com/rust-lang/rust-clippy/pull/5181) -* Add more constants to `approx_constant` [#5193](https://github.com/rust-lang/rust-clippy/pull/5193) -* Extend `question_mark` lint [#5266](https://github.com/rust-lang/rust-clippy/pull/5266) -* Also lint constants in `cmp_nan` [#4910](https://github.com/rust-lang/rust-clippy/pull/4910) -* Fix false negative in `expect_fun_call` [#4915](https://github.com/rust-lang/rust-clippy/pull/4915) -* Fix false negative in `redundant_clone` [#5017](https://github.com/rust-lang/rust-clippy/pull/5017) -* Fix false positive in `map_clone` [#4937](https://github.com/rust-lang/rust-clippy/pull/4937) -* Fix false positive in `replace_consts` [#4977](https://github.com/rust-lang/rust-clippy/pull/4977) -* Fix false positive in `let_and_return` [#5008](https://github.com/rust-lang/rust-clippy/pull/5008) -* Fix false positive in `use_debug` [#5047](https://github.com/rust-lang/rust-clippy/pull/5047) -* Fix false positive in `eq_op` [#5079](https://github.com/rust-lang/rust-clippy/pull/5079) -* Fix false positive in `possible_missing_comma` [#5083](https://github.com/rust-lang/rust-clippy/pull/5083) -* Fix false positive in `debug_assert_with_mut_call` [#5106](https://github.com/rust-lang/rust-clippy/pull/5106) -* Fix false positive in `unnecessary_unwrap` [#5132](https://github.com/rust-lang/rust-clippy/pull/5132) -* Fix false positive in `zero_prefixed_literal` [#5170](https://github.com/rust-lang/rust-clippy/pull/5170) -* Fix false positive in `missing_const_for_fn` [#5216](https://github.com/rust-lang/rust-clippy/pull/5216) -* Don't trigger `let_underscore_must_use` in external macros +* Add more constants to [`approx_constant`] [#5193](https://github.com/rust-lang/rust-clippy/pull/5193) +* Extend [`question_mark`] lint [#5266](https://github.com/rust-lang/rust-clippy/pull/5266) +* Also lint constants in [`cmp_nan`] [#4910](https://github.com/rust-lang/rust-clippy/pull/4910) +* Fix false negative in [`expect_fun_call`] [#4915](https://github.com/rust-lang/rust-clippy/pull/4915) +* Fix false negative in [`redundant_clone`] [#5017](https://github.com/rust-lang/rust-clippy/pull/5017) + +### False Positive Fixes + +* [`map_clone`] [#4937](https://github.com/rust-lang/rust-clippy/pull/4937) +* [`replace_consts`] [#4977](https://github.com/rust-lang/rust-clippy/pull/4977) +* [`let_and_return`] [#5008](https://github.com/rust-lang/rust-clippy/pull/5008) +* [`use_debug`] [#5047](https://github.com/rust-lang/rust-clippy/pull/5047) +* [`eq_op`] [#5079](https://github.com/rust-lang/rust-clippy/pull/5079) +* [`possible_missing_comma`] [#5083](https://github.com/rust-lang/rust-clippy/pull/5083) +* [`debug_assert_with_mut_call`] [#5106](https://github.com/rust-lang/rust-clippy/pull/5106) +* [`unnecessary_unwrap`] [#5132](https://github.com/rust-lang/rust-clippy/pull/5132) +* [`zero_prefixed_literal`] [#5170](https://github.com/rust-lang/rust-clippy/pull/5170) +* [`missing_const_for_fn`] [#5216](https://github.com/rust-lang/rust-clippy/pull/5216) +* Don't trigger [`let_underscore_must_use`] in external macros [#5082](https://github.com/rust-lang/rust-clippy/pull/5082) -* Don't trigger `empty_loop` in `no_std` crates [#5086](https://github.com/rust-lang/rust-clippy/pull/5086) -* Improve suggestion for `option_map_unwrap_or` [#4634](https://github.com/rust-lang/rust-clippy/pull/4634) -* Improve suggestion for `wildcard_enum_match_arm` [#4934](https://github.com/rust-lang/rust-clippy/pull/4934) -* Improve suggestion for `cognitive_complexity` [#4935](https://github.com/rust-lang/rust-clippy/pull/4935) -* Improve suggestion for `decimal_literal_representation` [#4956](https://github.com/rust-lang/rust-clippy/pull/4956) -* Improve suggestion for `unknown_clippy_lints` [#4963](https://github.com/rust-lang/rust-clippy/pull/4963) -* Improve suggestion for `explicit_into_iter_loop` [#4978](https://github.com/rust-lang/rust-clippy/pull/4978) -* Improve suggestion for `useless_attribute` [#5022](https://github.com/rust-lang/rust-clippy/pull/5022) -* Improve suggestion for `if_let_some_result` [#5032](https://github.com/rust-lang/rust-clippy/pull/5032) +* Don't trigger [`empty_loop`] in `no_std` crates [#5086](https://github.com/rust-lang/rust-clippy/pull/5086) + +### Suggestion Improvements + +* [`option_map_unwrap_or`] [#4634](https://github.com/rust-lang/rust-clippy/pull/4634) +* [`wildcard_enum_match_arm`] [#4934](https://github.com/rust-lang/rust-clippy/pull/4934) +* [`cognitive_complexity`] [#4935](https://github.com/rust-lang/rust-clippy/pull/4935) +* [`decimal_literal_representation`] [#4956](https://github.com/rust-lang/rust-clippy/pull/4956) +* [`unknown_clippy_lints`] [#4963](https://github.com/rust-lang/rust-clippy/pull/4963) +* [`explicit_into_iter_loop`] [#4978](https://github.com/rust-lang/rust-clippy/pull/4978) +* [`useless_attribute`] [#5022](https://github.com/rust-lang/rust-clippy/pull/5022) +* [`if_let_some_result`] [#5032](https://github.com/rust-lang/rust-clippy/pull/5032) * Improve suggestion when blocks of code are suggested [#5134](https://github.com/rust-lang/rust-clippy/pull/5134) -* Fix ICE in `unsound_collection_transmute` [#4975](https://github.com/rust-lang/rust-clippy/pull/4975) -* Fix ICE in `misc_early` lints [#5129](https://github.com/rust-lang/rust-clippy/pull/5129) -* Fix ICE in `missing_errors_doc` [#5213](https://github.com/rust-lang/rust-clippy/pull/5213) + +### ICE fixes + +* [`unsound_collection_transmute`] [#4975](https://github.com/rust-lang/rust-clippy/pull/4975) +* `misc_early` lints [#5129](https://github.com/rust-lang/rust-clippy/pull/5129) +* [`missing_errors_doc`] [#5213](https://github.com/rust-lang/rust-clippy/pull/5213) * Fix ICE when evaluating `usize`s [#5256](https://github.com/rust-lang/rust-clippy/pull/5256) + +### Documentation + * Improve documentation of `empty_enum`, `replace_consts`, `redundant_clone`, and `iterator_step_by_zero` * Add documentation pages for stable releases [#5171](https://github.com/rust-lang/rust-clippy/pull/5171) -* Clippy now runs completely on GitHub Actions [#5190](https://github.com/rust-lang/rust-clippy/pull/5190) + +### Others + +* Clippy now completely runs on GitHub Actions [#5190](https://github.com/rust-lang/rust-clippy/pull/5190) + ## Rust 1.41 From f56b0a1b347342d6244bb533f820ed0f93244c4e Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Fri, 13 Mar 2020 17:07:11 +0000 Subject: [PATCH 214/243] Document that wildcard_imports doesn't warn about `use ...::prelude::*;` --- clippy_lints/src/wildcard_imports.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 17e067a095de..6f8cec7c0567 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -43,6 +43,10 @@ declare_clippy_lint! { /// /// This can lead to confusing error messages at best and to unexpected behavior at worst. /// + /// Note that this will not warn about wildcard imports from modules named `prelude`; many + /// crates (including the standard library) provide modules named "prelude" specifically + /// designed for wildcard import. + /// /// **Known problems:** If macros are imported through the wildcard, this macro is not included /// by the suggestion and has to be added by hand. /// From 34a00fe7f47e592bc777b1a8e04df11b601b0888 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 13 Mar 2020 18:22:51 -0700 Subject: [PATCH 215/243] Remove git2 dependency. --- Cargo.toml | 3 +-- tests/integration.rs | 8 +++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cfcdaf22291c..8421670a1a46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,6 @@ clippy_lints = { version = "0.0.212", path = "clippy_lints" } regex = "1" semver = "0.9" rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"} -git2 = { version = "0.12", optional = true } tempfile = { version = "3.1.0", optional = true } lazy_static = "1.0" @@ -60,4 +59,4 @@ rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"} [features] deny-warnings = [] -integration = ["git2", "tempfile"] +integration = ["tempfile"] diff --git a/tests/integration.rs b/tests/integration.rs index 74f9a854dc1f..93dd66008f49 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -1,7 +1,5 @@ #![cfg(feature = "integration")] -use git2::Repository; - use std::env; use std::process::Command; @@ -19,7 +17,11 @@ fn integration_test() { .path() .join(crate_name); - Repository::clone(&repo_url, &repo_dir).expect("clone of repo failed"); + let st = Command::new("git") + .args(&["clone", "--depth=1", &repo_url, repo_dir.to_str().unwrap()]) + .status() + .expect("unstable to run git"); + assert!(st.success()); let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); let target_dir = std::path::Path::new(&root_dir).join("target"); From 626f2fe1cb68e88d7efe62822f4601217d2870ae Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Sat, 14 Mar 2020 10:22:49 +0100 Subject: [PATCH 216/243] Fix typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Mateusz Mikuła --- tests/integration.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration.rs b/tests/integration.rs index 93dd66008f49..0efbec18b4f7 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -20,7 +20,7 @@ fn integration_test() { let st = Command::new("git") .args(&["clone", "--depth=1", &repo_url, repo_dir.to_str().unwrap()]) .status() - .expect("unstable to run git"); + .expect("unable to run git"); assert!(st.success()); let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); From 29df0139dc4b7407e1a867dd76a9df35f2bff08f Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sat, 14 Mar 2020 19:29:48 +0700 Subject: [PATCH 217/243] Use pattern matching instead of manually checking condition --- tests/integration.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tests/integration.rs b/tests/integration.rs index 0efbec18b4f7..00eb140544f3 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -68,13 +68,8 @@ fn integration_test() { } match output.status.code() { - Some(code) => { - if code == 0 { - println!("Compilation successful"); - } else { - eprintln!("Compilation failed. Exit code: {}", code); - } - }, + Some(0) => println!("Compilation successful"), + Some(code) => eprintln!("Compilation failed. Exit code: {}", code), None => panic!("Process terminated by signal"), } } From 6be02209672e4bcd8cf96cb417216a0abe1b4fe3 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sat, 14 Mar 2020 15:17:52 +0000 Subject: [PATCH 218/243] Use `into_path` --- tests/integration.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/integration.rs b/tests/integration.rs index 00eb140544f3..8cc78c98a654 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -12,10 +12,8 @@ fn integration_test() { .nth(1) .expect("repo name should have format `/`"); - let repo_dir = tempfile::tempdir() - .expect("couldn't create temp dir") - .path() - .join(crate_name); + let mut repo_dir = tempfile::tempdir().expect("couldn't create temp dir").into_path(); + repo_dir.push(crate_name); let st = Command::new("git") .args(&["clone", "--depth=1", &repo_url, repo_dir.to_str().unwrap()]) From 9febcf5e8d4f29b12e5c5d77da174d0a3d21008b Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sat, 14 Mar 2020 14:30:08 +0000 Subject: [PATCH 219/243] Don't convert Path to lossy str --- tests/integration.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/integration.rs b/tests/integration.rs index 8cc78c98a654..4f373e034bc2 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -1,6 +1,7 @@ #![cfg(feature = "integration")] use std::env; +use std::ffi::OsStr; use std::process::Command; #[cfg_attr(feature = "integration", test)] @@ -16,7 +17,12 @@ fn integration_test() { repo_dir.push(crate_name); let st = Command::new("git") - .args(&["clone", "--depth=1", &repo_url, repo_dir.to_str().unwrap()]) + .args(&[ + OsStr::new("clone"), + OsStr::new("--depth=1"), + OsStr::new(&repo_url), + OsStr::new(&repo_dir), + ]) .status() .expect("unable to run git"); assert!(st.success()); From 00861d100dabcb6698963663b5a59f51f1b58e79 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 15 Mar 2020 05:26:32 +0900 Subject: [PATCH 220/243] Rustup to rust-lang/rust#69076 --- clippy_lints/src/len_zero.rs | 2 +- clippy_lints/src/lib.rs | 2 ++ clippy_lints/src/needless_pass_by_value.rs | 4 ++-- clippy_lints/src/utils/mod.rs | 6 ++++-- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 48881e1c2f03..00cfb3b718d7 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -134,7 +134,7 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item<'_>, trait_i // fill the set with current and super traits fn fill_trait_set(traitt: DefId, set: &mut FxHashSet, cx: &LateContext<'_, '_>) { if set.insert(traitt) { - for supertrait in rustc_infer::traits::supertrait_def_ids(cx.tcx, traitt) { + for supertrait in rustc_trait_selection::traits::supertrait_def_ids(cx.tcx, traitt) { fill_trait_set(supertrait, set, cx); } } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1eac69678a64..791307ba43f4 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -51,6 +51,8 @@ extern crate rustc_span; #[allow(unused_extern_crates)] extern crate rustc_target; #[allow(unused_extern_crates)] +extern crate rustc_trait_selection; +#[allow(unused_extern_crates)] extern crate rustc_typeck; use rustc::session::Session; diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 01343341726a..d2d2b48c9cf2 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -12,12 +12,12 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir::intravisit::FnKind; use rustc_hir::{BindingAnnotation, Body, FnDecl, GenericArg, HirId, ItemKind, Node, PatKind, QPath, TyKind}; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits; -use rustc_infer::traits::misc::can_type_implement_copy; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{Span, Symbol}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::traits; +use rustc_trait_selection::traits::misc::can_type_implement_copy; use rustc_typeck::expr_use_visitor as euv; use std::borrow::Cow; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 9f7cf4007657..e32164c8bb10 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -47,12 +47,14 @@ use rustc_hir::{ MatchSource, Param, Pat, PatKind, Path, PathSegment, QPath, TraitItem, TraitItemKind, TraitRef, TyKind, Unsafety, }; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::predicate_for_trait_def; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::original_sp; use rustc_span::symbol::{self, kw, Symbol}; use rustc_span::{BytePos, Pos, Span, DUMMY_SP}; +use rustc_trait_selection::traits::predicate_for_trait_def; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; +use rustc_trait_selection::traits::query::normalize::AtExt; use smallvec::SmallVec; use crate::consts::{constant, Constant}; @@ -1387,7 +1389,7 @@ pub fn is_trait_impl_item(cx: &LateContext<'_, '_>, hir_id: HirId) -> bool { /// } /// ``` pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_, '_>, did: DefId) -> bool { - use rustc_infer::traits; + use rustc_trait_selection::traits; let predicates = cx .tcx .predicates_of(did) From 4d8ed5a84293fb435c71447169e9b387c4988b47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 15 Mar 2020 18:23:43 +0100 Subject: [PATCH 221/243] rustup https://github.com/rust-lang/rust/pull/69589/ --- clippy_lints/src/dbg_macro.rs | 2 +- clippy_lints/src/non_expressive_names.rs | 6 +++--- clippy_lints/src/utils/sugg.rs | 2 +- clippy_lints/src/write.rs | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index 67f86f50ef61..f9bf1141a8b2 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -30,7 +30,7 @@ declare_clippy_lint! { declare_lint_pass!(DbgMacro => [DBG_MACRO]); impl EarlyLintPass for DbgMacro { - fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) { + fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::MacCall) { if mac.path == sym!(dbg) { if let Some(sugg) = tts_span(mac.args.inner_tokens()).and_then(|span| snippet_opt(cx, span)) { span_lint_and_sugg( diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 847eb0eaf025..98446eef9d73 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -1,6 +1,6 @@ use crate::utils::{span_lint, span_lint_and_then}; use rustc_ast::ast::{ - Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, Ident, Item, ItemKind, Local, Mac, Pat, PatKind, + Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, Ident, Item, ItemKind, Local, MacCall, Pat, PatKind, }; use rustc_ast::attr; use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor}; @@ -145,7 +145,7 @@ impl<'a, 'tcx, 'b> Visitor<'tcx> for SimilarNamesNameVisitor<'a, 'tcx, 'b> { _ => walk_pat(self, pat), } } - fn visit_mac(&mut self, _mac: &Mac) { + fn visit_mac(&mut self, _mac: &MacCall) { // do not check macs } } @@ -347,7 +347,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> { fn visit_item(&mut self, _: &Item) { // do not recurse into inner items } - fn visit_mac(&mut self, _mac: &Mac) { + fn visit_mac(&mut self, _mac: &MacCall) { // do not check macs } } diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index 8cf3c07a2d42..b2c4027b9f11 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -154,7 +154,7 @@ impl<'a> Sugg<'a> { | ast::ExprKind::InlineAsm(..) | ast::ExprKind::Lit(..) | ast::ExprKind::Loop(..) - | ast::ExprKind::Mac(..) + | ast::ExprKind::MacCall(..) | ast::ExprKind::MethodCall(..) | ast::ExprKind::Paren(..) | ast::ExprKind::Path(..) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index d772427889ed..a63c6771bb53 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::ops::Range; use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_sugg, span_lint_and_then}; -use rustc_ast::ast::{Expr, ExprKind, Item, ItemKind, Mac, StrLit, StrStyle}; +use rustc_ast::ast::{Expr, ExprKind, Item, ItemKind, MacCall, StrLit, StrStyle}; use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_errors::Applicability; @@ -216,7 +216,7 @@ impl EarlyLintPass for Write { self.in_debug_impl = false; } - fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &Mac) { + fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &MacCall) { if mac.path == sym!(println) { span_lint(cx, PRINT_STDOUT, mac.span(), "use of `println!`"); if let (Some(fmt_str), _) = self.check_tts(cx, &mac.args.inner_tokens(), false) { From 548c417ec4b9f6ea229ef9b680e3a881873a3f8a Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 16 Mar 2020 07:23:03 +0100 Subject: [PATCH 222/243] Make use of `or_patterns` feature --- clippy_lints/src/consts.rs | 2 +- clippy_lints/src/eval_order_dependence.rs | 6 ++---- clippy_lints/src/lib.rs | 1 + clippy_lints/src/lifetimes.rs | 2 +- clippy_lints/src/loops.rs | 2 +- clippy_lints/src/methods/mod.rs | 4 +--- clippy_lints/src/no_effect.rs | 2 +- clippy_lints/src/non_copy_const.rs | 2 +- clippy_lints/src/utils/mod.rs | 13 +++++++------ 9 files changed, 16 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index ec8ba70bf741..fc26755a3754 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -320,7 +320,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'cc>) -> Option { let res = self.tables.qpath_res(qpath, id); match res { - Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => { + Res::Def(DefKind::Const | DefKind::AssocConst, def_id) => { let substs = self.tables.node_substs(id); let substs = if self.substs.is_empty() { substs diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index d6b847d1dbb1..7fe13b9cc673 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -106,10 +106,8 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> { ExprKind::Match(ref e, arms, _) => { self.visit_expr(e); for arm in arms { - if let Some(ref guard) = arm.guard { - match guard { - Guard::If(if_expr) => self.visit_expr(if_expr), - } + if let Some(Guard::If(if_expr)) = arm.guard { + self.visit_expr(if_expr) } // make sure top level arm expressions aren't linted self.maybe_walk_expr(&*arm.body); diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 791307ba43f4..fb79ad271e0a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -2,6 +2,7 @@ #![feature(box_syntax)] #![feature(box_patterns)] +#![feature(or_patterns)] #![feature(rustc_private)] #![feature(stmt_expr_attributes)] #![allow(clippy::missing_docs_in_private_items, clippy::must_use_candidate)] diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 3b687bd54a1c..02aca996adcd 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -346,7 +346,7 @@ impl<'v, 't> RefVisitor<'v, 't> { { let hir_id = ty.hir_id; match self.cx.tables.qpath_res(qpath, hir_id) { - Res::Def(DefKind::TyAlias, def_id) | Res::Def(DefKind::Struct, def_id) => { + Res::Def(DefKind::TyAlias | DefKind::Struct, def_id) => { let generics = self.cx.tcx.generics_of(def_id); for _ in generics.params.as_slice() { self.record(&None); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 006281a1b5b5..ee4199c5f12d 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1780,7 +1780,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> { } return false; // no need to walk further *on the variable* } - Res::Def(DefKind::Static, ..) | Res::Def(DefKind::Const, ..) => { + Res::Def(DefKind::Static | DefKind::Const, ..) => { if indexed_indirectly { self.indexed_indirectly.insert(seqvar.segments[0].ident.name, None); } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 19d9a31aaf41..f287ede61e69 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1755,9 +1755,7 @@ fn lint_expect_fun_call( ) }), hir::ExprKind::Path(ref p) => match cx.tables.qpath_res(p, arg.hir_id) { - hir::def::Res::Def(hir::def::DefKind::Const, _) | hir::def::Res::Def(hir::def::DefKind::Static, _) => { - true - }, + hir::def::Res::Def(hir::def::DefKind::Const | hir::def::DefKind::Static, _) => true, _ => false, }, _ => false, diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 6383d3ca2454..b8bfa676a160 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -69,7 +69,7 @@ fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { if let ExprKind::Path(ref qpath) = callee.kind { let res = qpath_res(cx, qpath, callee.hir_id); match res { - Res::Def(DefKind::Struct, ..) | Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(..), _) => { + Res::Def(DefKind::Struct | DefKind::Variant | DefKind::Ctor(..), ..) => { !has_drop(cx, cx.tables.expr_ty(expr)) && args.iter().all(|arg| has_no_effect(cx, arg)) }, _ => false, diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 908d1fe286d4..43d76d0cbbdd 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -191,7 +191,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst { // Make sure it is a const item. match qpath_res(cx, qpath, expr.hir_id) { - Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => {}, + Res::Def(DefKind::Const | DefKind::AssocConst, _) => {}, _ => return, }; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index e32164c8bb10..eb5e01341776 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -315,7 +315,7 @@ pub fn get_trait_def_id(cx: &LateContext<'_, '_>, path: &[&str]) -> Option Some(trait_id), + Res::Def(DefKind::Trait | DefKind::TraitAlias, trait_id) => Some(trait_id), Res::Err => unreachable!("this trait resolution is impossible: {:?}", &path), _ => None, } @@ -448,10 +448,11 @@ pub fn is_entrypoint_fn(cx: &LateContext<'_, '_>, def_id: DefId) -> bool { pub fn get_item_name(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option { let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id); match cx.tcx.hir().find(parent_id) { - Some(Node::Item(&Item { ref ident, .. })) => Some(ident.name), - Some(Node::TraitItem(&TraitItem { ident, .. })) | Some(Node::ImplItem(&ImplItem { ident, .. })) => { - Some(ident.name) - }, + Some( + Node::Item(Item { ident, .. }) + | Node::TraitItem(TraitItem { ident, .. }) + | Node::ImplItem(ImplItem { ident, .. }), + ) => Some(ident.name), _ => None, } } @@ -925,7 +926,7 @@ pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_, '_>, expr: &Exp if let ExprKind::Path(ref qp) = fun.kind { let res = cx.tables.qpath_res(qp, fun.hir_id); return match res { - def::Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(..), _) => true, + def::Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true, def::Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id), _ => false, }; From ba0884bee37dc386116a8ba87c33a602c1864d68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 15 Mar 2020 23:41:20 +0100 Subject: [PATCH 223/243] rustup https://github.com/rust-lang/rust/pull/68944 --- clippy_lints/src/assign_ops.rs | 2 +- clippy_lints/src/block_in_if_condition.rs | 2 +- clippy_lints/src/booleans.rs | 4 ++-- clippy_lints/src/cognitive_complexity.rs | 2 +- clippy_lints/src/doc.rs | 2 +- clippy_lints/src/entry.rs | 2 +- clippy_lints/src/escape.rs | 4 ++-- clippy_lints/src/eval_order_dependence.rs | 4 ++-- clippy_lints/src/fallible_impl_from.rs | 2 +- clippy_lints/src/functions.rs | 4 ++-- clippy_lints/src/let_if_seq.rs | 2 +- clippy_lints/src/lifetimes.rs | 6 +++--- clippy_lints/src/loops.rs | 18 +++++++++--------- clippy_lints/src/methods/mod.rs | 4 ++-- .../src/methods/option_map_unwrap_or.rs | 8 ++++---- .../src/methods/unnecessary_filter_map.rs | 2 +- clippy_lints/src/missing_doc.rs | 2 +- clippy_lints/src/mut_mut.rs | 2 +- clippy_lints/src/mutable_debug_assertion.rs | 4 ++-- clippy_lints/src/slow_vector_initialization.rs | 2 +- clippy_lints/src/suspicious_trait_impl.rs | 2 +- clippy_lints/src/types.rs | 8 ++++---- clippy_lints/src/unused_self.rs | 4 ++-- clippy_lints/src/unwrap.rs | 4 ++-- clippy_lints/src/use_self.rs | 6 +++--- clippy_lints/src/utils/author.rs | 2 +- clippy_lints/src/utils/internal_lints.rs | 4 ++-- clippy_lints/src/utils/mod.rs | 4 ++-- clippy_lints/src/utils/ptr.rs | 2 +- clippy_lints/src/utils/usage.rs | 2 +- 30 files changed, 58 insertions(+), 58 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index bc4e47340c69..b6fb6fdd2cc0 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -256,7 +256,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> { walk_expr(self, expr); } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index d004dcddfea0..56b4e5522f4e 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -66,7 +66,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> { } walk_expr(self, expr); } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index ccaa277efbda..b580240be175 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -457,7 +457,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> { _ => walk_expr(self, e), } } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } @@ -491,7 +491,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NotSimplificationVisitor<'a, 'tcx> { walk_expr(self, expr); } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs index d0f15d2373a7..fcab45901884 100644 --- a/clippy_lints/src/cognitive_complexity.rs +++ b/clippy_lints/src/cognitive_complexity.rs @@ -156,7 +156,7 @@ impl<'tcx> Visitor<'tcx> for CCHelper { _ => {}, } } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 006d732703ec..ed870850a8c4 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -148,7 +148,7 @@ impl_lint_pass!(DocMarkdown => [DOC_MARKDOWN, MISSING_SAFETY_DOC, MISSING_ERRORS impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DocMarkdown { fn check_crate(&mut self, cx: &LateContext<'a, 'tcx>, krate: &'tcx hir::Crate<'_>) { - check_attrs(cx, &self.valid_idents, &krate.attrs); + check_attrs(cx, &self.valid_idents, &krate.item.attrs); } fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item<'_>) { diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 19da4c4bc9a5..88647be02641 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -181,7 +181,7 @@ impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> { walk_expr(self, expr); } } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 850c7f728bd2..db55e5ed141e 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -92,7 +92,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxedLocal { } // TODO: Replace with Map::is_argument(..) when it's fixed -fn is_argument(map: &rustc::hir::map::Map<'_>, id: HirId) -> bool { +fn is_argument(map: rustc::hir::map::Map<'_>, id: HirId) -> bool { match map.find(id) { Some(Node::Binding(_)) => (), _ => return false, @@ -136,7 +136,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { fn mutate(&mut self, cmt: &Place<'tcx>) { if cmt.projections.is_empty() { let map = &self.cx.tcx.hir(); - if is_argument(map, cmt.hir_id) { + if is_argument(*map, cmt.hir_id) { // Skip closure arguments let parent_id = map.get_parent_node(cmt.hir_id); if let Some(Node::Expr(..)) = map.find(map.get_parent_node(parent_id)) { diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index d6b847d1dbb1..9292dba3bd25 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -158,7 +158,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { fn visit_block(&mut self, _: &'tcx Block<'_>) { // don't continue over blocks, LateLintPass already does that } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } @@ -341,7 +341,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> { walk_expr(self, expr); } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 19a122594cb7..5ed7fd49f472 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -85,7 +85,7 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it intravisit::walk_expr(self, expr); } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index c43b2075b646..23e3371c5fb6 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -561,7 +561,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> { intravisit::walk_expr(self, expr); } - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None } } @@ -624,7 +624,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> { } } - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None } } diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index a4c5c003b7f8..d5343852208b 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -158,7 +158,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for UsedVisitor<'a, 'tcx> { } intravisit::walk_expr(self, expr); } - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None } } diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 3b687bd54a1c..a9408e369b39 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -407,7 +407,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { } walk_ty(self, ty); } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } @@ -479,7 +479,7 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker { walk_generic_param(self, param) } } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } @@ -522,7 +522,7 @@ impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker { } } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 006281a1b5b5..bd71d68848d6 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1712,7 +1712,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LocalUsedVisitor<'a, 'tcx> { } } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } @@ -1885,7 +1885,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { } self.prefer_mutable = old; } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } @@ -1942,7 +1942,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarUsedAfterLoopVisitor<'a, 'tcx> { } walk_expr(self, expr); } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } @@ -2084,7 +2084,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> { } walk_expr(self, expr); } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } @@ -2176,8 +2176,8 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { walk_expr(self, expr); } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.cx.tcx.hir()) } } @@ -2312,7 +2312,7 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor { walk_pat(self, pat) } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } @@ -2398,7 +2398,7 @@ impl<'a, 'tcx> Visitor<'tcx> for HasBreakOrReturnVisitor { walk_expr(self, expr); } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } @@ -2449,7 +2449,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> { } } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 19d9a31aaf41..7109cd5cf914 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1545,7 +1545,7 @@ fn lint_or_fun_call<'a, 'tcx>( } } - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None } } @@ -3453,7 +3453,7 @@ fn contains_return(expr: &hir::Expr<'_>) -> bool { } } - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None } } diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index 4df963a4f796..c40ab7beba44 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -99,8 +99,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> { walk_path(self, path); } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.cx.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.cx.tcx.hir()) } } @@ -121,8 +121,8 @@ impl<'a, 'tcx> Visitor<'tcx> for MapExprVisitor<'a, 'tcx> { walk_path(self, path); } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.cx.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.cx.tcx.hir()) } } diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs index fdfae8cd190c..ee6c6ef12e56 100644 --- a/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -136,7 +136,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReturnVisitor<'a, 'tcx> { } } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 57bec0a65b37..88467f3057f5 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -125,7 +125,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { } fn check_crate(&mut self, cx: &LateContext<'a, 'tcx>, krate: &'tcx hir::Crate<'_>) { - self.check_missing_docs_attrs(cx, &krate.attrs, krate.span, "crate"); + self.check_missing_docs_attrs(cx, &krate.item.attrs, krate.item.span, "crate"); } fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item<'_>) { diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 988484591660..70061f2aa83b 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -108,7 +108,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { intravisit::walk_ty(self, ty); } - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None } } diff --git a/clippy_lints/src/mutable_debug_assertion.rs b/clippy_lints/src/mutable_debug_assertion.rs index f0c5c95b1d49..75225fa8c42b 100644 --- a/clippy_lints/src/mutable_debug_assertion.rs +++ b/clippy_lints/src/mutable_debug_assertion.rs @@ -155,7 +155,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MutArgVisitor<'a, 'tcx> { walk_expr(self, expr) } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.cx.tcx.hir()) } } diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index 8d8dbe0e4083..61dc7d1c9c5a 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -318,7 +318,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> { walk_expr(self, expr); } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index 40e1b4abc796..e39a7b5e2ab6 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -197,7 +197,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BinaryExprVisitor { walk_expr(self, expr); } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index fbd3f37c5643..d44aa492508a 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1554,7 +1554,7 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { walk_ty(self, ty); self.nest -= sub_nest; } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } @@ -2309,7 +2309,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ImplicitHasherTypeVisitor<'a, 'tcx> { walk_ty(self, t); } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } @@ -2386,8 +2386,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 't walk_expr(self, e); } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.cx.tcx.hir()) } } diff --git a/clippy_lints/src/unused_self.rs b/clippy_lints/src/unused_self.rs index 9f1a7aaf977c..8579fd73fbb7 100644 --- a/clippy_lints/src/unused_self.rs +++ b/clippy_lints/src/unused_self.rs @@ -107,7 +107,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnusedSelfVisitor<'a, 'tcx> { walk_path(self, path); } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.cx.tcx.hir()) } } diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 79dd93e64ff8..767b48d4a096 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -185,8 +185,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { } } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.cx.tcx.hir()) } } diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 4170dcc7fadf..e1316fa0a3db 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -113,7 +113,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TraitImplTyVisitor<'a, 'tcx> { walk_ty(self, t) } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } @@ -275,7 +275,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { } } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.cx.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.cx.tcx.hir()) } } diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index e2a19d633b3e..e95c45852ac2 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -689,7 +689,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { } } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index c348f5794b9c..7dbb0d5a9ab8 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -299,8 +299,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LintCollector<'a, 'tcx> { self.output.insert(path.segments[0].ident.name); } } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.cx.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.cx.tcx.hir()) } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index e32164c8bb10..62c47f0afd1d 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -479,7 +479,7 @@ impl<'tcx> Visitor<'tcx> for ContainsName { self.result = true; } } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } @@ -1355,7 +1355,7 @@ pub fn is_must_use_func_call(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool } pub fn is_no_std_crate(krate: &Crate<'_>) -> bool { - krate.attrs.iter().any(|attr| { + krate.item.attrs.iter().any(|attr| { if let ast::AttrKind::Normal(ref attr) = attr.kind { attr.path == symbol::sym::no_std } else { diff --git a/clippy_lints/src/utils/ptr.rs b/clippy_lints/src/utils/ptr.rs index 176edcf1652f..238c2277a932 100644 --- a/clippy_lints/src/utils/ptr.rs +++ b/clippy_lints/src/utils/ptr.rs @@ -78,7 +78,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> { walk_expr(self, expr); } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs index 5871cf45ef90..7cde18fdb3b4 100644 --- a/clippy_lints/src/utils/usage.rs +++ b/clippy_lints/src/utils/usage.rs @@ -93,7 +93,7 @@ impl<'tcx> Visitor<'tcx> for UsedVisitor { } } - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } From a97f60b8e31e1913c0b937bc2adcfb5e9e123120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 16 Mar 2020 16:00:16 +0100 Subject: [PATCH 224/243] rustup https://github.com/rust-lang/rust/pull/69738 --- clippy_lints/src/attrs.rs | 8 ++++---- clippy_lints/src/doc.rs | 2 +- clippy_lints/src/fallible_impl_from.rs | 2 +- clippy_lints/src/functions.rs | 4 ++-- clippy_lints/src/inherent_to_string.rs | 2 +- clippy_lints/src/inline_fn_without_body.rs | 4 ++-- clippy_lints/src/lifetimes.rs | 8 ++++---- clippy_lints/src/methods/mod.rs | 4 ++-- clippy_lints/src/missing_doc.rs | 2 +- clippy_lints/src/missing_inline.rs | 2 +- clippy_lints/src/mut_key.rs | 2 +- clippy_lints/src/new_without_default.rs | 2 +- clippy_lints/src/ptr.rs | 6 +++--- clippy_lints/src/types.rs | 6 +++--- clippy_lints/src/unused_self.rs | 2 +- clippy_lints/src/use_self.rs | 2 +- clippy_lints/src/utils/inspector.rs | 2 +- clippy_lints/src/utils/mod.rs | 4 ++-- 18 files changed, 32 insertions(+), 32 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 833739f1bd3c..35cde05e7f57 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -12,7 +12,7 @@ use rustc_ast::ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, use rustc_ast::util::lev_distance::find_best_match_for_name; use rustc_errors::Applicability; use rustc_hir::{ - Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitItem, TraitItemKind, TraitMethod, + Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind, }; use rustc_lint::{CheckLintNameResult, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -372,15 +372,15 @@ fn is_relevant_item(cx: &LateContext<'_, '_>, item: &Item<'_>) -> bool { fn is_relevant_impl(cx: &LateContext<'_, '_>, item: &ImplItem<'_>) -> bool { match item.kind { - ImplItemKind::Method(_, eid) => is_relevant_expr(cx, cx.tcx.body_tables(eid), &cx.tcx.hir().body(eid).value), + ImplItemKind::Fn(_, eid) => is_relevant_expr(cx, cx.tcx.body_tables(eid), &cx.tcx.hir().body(eid).value), _ => false, } } fn is_relevant_trait(cx: &LateContext<'_, '_>, item: &TraitItem<'_>) -> bool { match item.kind { - TraitItemKind::Fn(_, TraitMethod::Required(_)) => true, - TraitItemKind::Fn(_, TraitMethod::Provided(eid)) => { + TraitItemKind::Fn(_, TraitFn::Required(_)) => true, + TraitItemKind::Fn(_, TraitFn::Provided(eid)) => { is_relevant_expr(cx, cx.tcx.body_tables(eid), &cx.tcx.hir().body(eid).value) }, _ => false, diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index ed870850a8c4..9b028cd0f76b 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -191,7 +191,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DocMarkdown { if self.in_trait_impl || in_external_macro(cx.tcx.sess, item.span) { return; } - if let hir::ImplItemKind::Method(ref sig, body_id) = item.kind { + if let hir::ImplItemKind::Fn(ref sig, body_id) = item.kind { lint_for_missing_headers(cx, item.hir_id, item.span, sig, headers, Some(body_id)); } } diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 5ed7fd49f472..06608772c8af 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -93,7 +93,7 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it for impl_item in impl_items { if_chain! { if impl_item.ident.name == sym!(from); - if let ImplItemKind::Method(_, body_id) = + if let ImplItemKind::Fn(_, body_id) = cx.tcx.hir().impl_item(impl_item.id).kind; then { // check the body for `begin_panic` or `unwrap` diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 23e3371c5fb6..01ced205af48 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -250,7 +250,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { } fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::ImplItem<'_>) { - if let hir::ImplItemKind::Method(ref sig, ref body_id) = item.kind { + if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind { let attr = must_use_attr(&item.attrs); if let Some(attr) = attr { let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); @@ -284,7 +284,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); check_needless_must_use(cx, &sig.decl, item.hir_id, item.span, fn_header_span, attr); } - if let hir::TraitMethod::Provided(eid) = *eid { + if let hir::TraitFn::Provided(eid) = *eid { let body = cx.tcx.hir().body(eid); Self::check_raw_ptr(cx, sig.header.unsafety, &sig.decl, body, item.hir_id); diff --git a/clippy_lints/src/inherent_to_string.rs b/clippy_lints/src/inherent_to_string.rs index 24c0b1cb80e6..ca8e834e347c 100644 --- a/clippy_lints/src/inherent_to_string.rs +++ b/clippy_lints/src/inherent_to_string.rs @@ -100,7 +100,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InherentToString { if_chain! { // Check if item is a method, called to_string and has a parameter 'self' - if let ImplItemKind::Method(ref signature, _) = impl_item.kind; + if let ImplItemKind::Fn(ref signature, _) = impl_item.kind; if impl_item.ident.name.as_str() == "to_string"; let decl = &signature.decl; if decl.implicit_self.has_implicit_self(); diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index 32032c4da885..08fc6287b776 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -4,7 +4,7 @@ use crate::utils::span_lint_and_then; use crate::utils::sugg::DiagnosticBuilderExt; use rustc_ast::ast::{Attribute, Name}; use rustc_errors::Applicability; -use rustc_hir::{TraitItem, TraitItemKind, TraitMethod}; +use rustc_hir::{TraitFn, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -32,7 +32,7 @@ declare_lint_pass!(InlineFnWithoutBody => [INLINE_FN_WITHOUT_BODY]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InlineFnWithoutBody { fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem<'_>) { - if let TraitItemKind::Fn(_, TraitMethod::Required(_)) = item.kind { + if let TraitItemKind::Fn(_, TraitFn::Required(_)) = item.kind { check_attrs(cx, item.ident.name, &item.attrs); } } diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 30ad32c8ed16..85d3e9029dff 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -9,7 +9,7 @@ use rustc_hir::intravisit::{ use rustc_hir::FnRetTy::Return; use rustc_hir::{ BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem, ImplItemKind, Item, - ItemKind, Lifetime, LifetimeName, ParamName, QPath, TraitBoundModifier, TraitItem, TraitItemKind, TraitMethod, Ty, + ItemKind, Lifetime, LifetimeName, ParamName, QPath, TraitBoundModifier, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereClause, WherePredicate, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -86,7 +86,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Lifetimes { } fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem<'_>) { - if let ImplItemKind::Method(ref sig, id) = item.kind { + if let ImplItemKind::Fn(ref sig, id) = item.kind { let report_extra_lifetimes = trait_ref_of_method(cx, item.hir_id).is_none(); check_fn_inner( cx, @@ -102,8 +102,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Lifetimes { fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem<'_>) { if let TraitItemKind::Fn(ref sig, ref body) = item.kind { let body = match *body { - TraitMethod::Required(_) => None, - TraitMethod::Provided(id) => Some(id), + TraitFn::Required(_) => None, + TraitFn::Provided(id) => Some(id), }; check_fn_inner(cx, &sig.decl, body, &item.generics, item.span, true); } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index ab51ecfb1b5d..8bba56c675ff 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1410,7 +1410,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { let def_id = cx.tcx.hir().local_def_id(item.hir_id); let ty = cx.tcx.type_of(def_id); if_chain! { - if let hir::ImplItemKind::Method(ref sig, id) = impl_item.kind; + if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind; if let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir().body(id)).next(); if let hir::ItemKind::Impl{ of_trait: None, .. } = item.kind; @@ -1469,7 +1469,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { } } - if let hir::ImplItemKind::Method(_, _) = impl_item.kind { + if let hir::ImplItemKind::Fn(_, _) = impl_item.kind { let ret_ty = return_ty(cx, impl_item.hir_id); // walk the return type and check for Self (this does not check associated types) diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 88467f3057f5..96750cb3b466 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -185,7 +185,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { let desc = match impl_item.kind { hir::ImplItemKind::Const(..) => "an associated constant", - hir::ImplItemKind::Method(..) => "a method", + hir::ImplItemKind::Fn(..) => "a method", hir::ImplItemKind::TyAlias(_) => "an associated type", hir::ImplItemKind::OpaqueTy(_) => "an existential type", }; diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index fad4d6d0fe2e..0f871d29c2f3 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -141,7 +141,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { } let desc = match impl_item.kind { - hir::ImplItemKind::Method(..) => "a method", + hir::ImplItemKind::Fn(..) => "a method", hir::ImplItemKind::Const(..) | hir::ImplItemKind::TyAlias(_) | hir::ImplItemKind::OpaqueTy(_) => return, }; diff --git a/clippy_lints/src/mut_key.rs b/clippy_lints/src/mut_key.rs index 61f514a740a5..adaf82c70748 100644 --- a/clippy_lints/src/mut_key.rs +++ b/clippy_lints/src/mut_key.rs @@ -59,7 +59,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableKeyType { } fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::ImplItem<'tcx>) { - if let hir::ImplItemKind::Method(ref sig, ..) = item.kind { + if let hir::ImplItemKind::Fn(ref sig, ..) = item.kind { if trait_ref_of_method(cx, item.hir_id).is_none() { check_sig(cx, item.hir_id, &sig.decl); } diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 303ba1e68087..adc93909677d 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -105,7 +105,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { if in_external_macro(cx.sess(), impl_item.span) { return; } - if let hir::ImplItemKind::Method(ref sig, _) = impl_item.kind { + if let hir::ImplItemKind::Fn(ref sig, _) = impl_item.kind { let name = impl_item.ident.name; let id = impl_item.hir_id; if sig.header.constness == hir::Constness::Const { diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index a6d62406aa76..3d420cf8cecf 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -10,7 +10,7 @@ use rustc::ty; use rustc_errors::Applicability; use rustc_hir::{ BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, HirId, ImplItem, ImplItemKind, Item, ItemKind, - Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitItem, TraitItemKind, TraitMethod, Ty, TyKind, + Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -109,7 +109,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ptr { } fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem<'_>) { - if let ImplItemKind::Method(ref sig, body_id) = item.kind { + if let ImplItemKind::Fn(ref sig, body_id) = item.kind { let parent_item = cx.tcx.hir().get_parent_item(item.hir_id); if let Some(Node::Item(it)) = cx.tcx.hir().find(parent_item) { if let ItemKind::Impl { of_trait: Some(_), .. } = it.kind { @@ -122,7 +122,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ptr { fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem<'_>) { if let TraitItemKind::Fn(ref sig, ref trait_method) = item.kind { - let body_id = if let TraitMethod::Provided(b) = *trait_method { + let body_id = if let TraitFn::Provided(b) = *trait_method { Some(b) } else { None diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index d44aa492508a..26d425cf2416 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -15,8 +15,8 @@ use rustc_hir as hir; use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::{ BinOpKind, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericParamKind, HirId, ImplItem, - ImplItemKind, Item, ItemKind, Lifetime, Local, MatchSource, MutTy, Mutability, QPath, Stmt, StmtKind, TraitItem, - TraitItemKind, TraitMethod, TyKind, UnOp, + ImplItemKind, Item, ItemKind, Lifetime, Local, MatchSource, MutTy, Mutability, QPath, Stmt, StmtKind, TraitFn, + TraitItem, TraitItemKind, TyKind, UnOp, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; @@ -1457,7 +1457,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexity { fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem<'_>) { match item.kind { TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => self.check_type(cx, ty), - TraitItemKind::Fn(FnSig { ref decl, .. }, TraitMethod::Required(_)) => self.check_fndecl(cx, decl), + TraitItemKind::Fn(FnSig { ref decl, .. }, TraitFn::Required(_)) => self.check_fndecl(cx, decl), // methods with default impl are covered by check_fn _ => (), } diff --git a/clippy_lints/src/unused_self.rs b/clippy_lints/src/unused_self.rs index 8579fd73fbb7..a45b4a6869c5 100644 --- a/clippy_lints/src/unused_self.rs +++ b/clippy_lints/src/unused_self.rs @@ -58,7 +58,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedSelf { kind: AssocItemKind::Method { has_self: true }, .. } = impl_item_ref; - if let ImplItemKind::Method(_, body_id) = &impl_item.kind; + if let ImplItemKind::Fn(_, body_id) = &impl_item.kind; let body = cx.tcx.hir().body(*body_id); if !body.params.is_empty(); then { diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index e1316fa0a3db..73a986b79011 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -195,7 +195,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { if let Some(impl_trait_ref) = impl_trait_ref { for impl_item_ref in refs { let impl_item = cx.tcx.hir().impl_item(impl_item_ref.id); - if let ImplItemKind::Method(FnSig{ decl: impl_decl, .. }, impl_body_id) + if let ImplItemKind::Fn(FnSig{ decl: impl_decl, .. }, impl_body_id) = &impl_item.kind { let item_type = cx.tcx.type_of(impl_def_id); check_trait_method_impl_decl(cx, item_type, impl_item, impl_decl, &impl_trait_ref); diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index a2a4dc4201b0..d79f6d525fcf 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -62,7 +62,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DeepCodeInspector { println!("associated constant"); print_expr(cx, &cx.tcx.hir().body(body_id).value, 1); }, - hir::ImplItemKind::Method(..) => println!("method"), + hir::ImplItemKind::Fn(..) => println!("method"), hir::ImplItemKind::TyAlias(_) => println!("associated type"), hir::ImplItemKind::OpaqueTy(_) => println!("existential type"), } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 2a8e172663d2..280e8e2f32e6 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -101,7 +101,7 @@ pub fn in_constant(cx: &LateContext<'_, '_>, id: HirId) -> bool { .. }) | Node::ImplItem(&ImplItem { - kind: ImplItemKind::Method(ref sig, _), + kind: ImplItemKind::Fn(ref sig, _), .. }) => sig.header.constness == Constness::Const, _ => false, @@ -758,7 +758,7 @@ pub fn get_enclosing_block<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, hir_id: HirId) .. }) | Node::ImplItem(&ImplItem { - kind: ImplItemKind::Method(_, eid), + kind: ImplItemKind::Fn(_, eid), .. }) => match cx.tcx.hir().body(eid).value.kind { ExprKind::Block(ref block, _) => Some(block), From b8effecee18256c88bf4189446cdacdff439210b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Tue, 17 Mar 2020 10:18:22 +0100 Subject: [PATCH 225/243] rustup https://github.com/rust-lang/rust/pull/69838 --- clippy_lints/src/write.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index a63c6771bb53..5ad43ad55a36 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -357,7 +357,7 @@ impl Write { }; let tts = tts.clone(); - let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, None, false, false, None); + let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, false, None); let mut expr: Option = None; if is_write { expr = match parser.parse_expr().map_err(|mut err| err.cancel()) { From 7545925ffef174a4951f564ca0c80bbb300ed6a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 18 Mar 2020 01:43:39 +0100 Subject: [PATCH 226/243] new_lint.rs: encourage authors to write more detailed code samples in lint descriptions (linted as well as fixed code) changelog: none --- clippy_dev/src/new_lint.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index a3ccb2758e25..9e2a4617cde5 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -131,7 +131,11 @@ declare_clippy_lint! {{ /// **Example:** /// /// ```rust - /// // example code + /// // example code where clippy issues a warning + /// ``` + /// Use instead: + /// ```rust + /// // example code which does not raise clippy warning /// ``` pub {name_upper}, {category}, From 2204bf20aea66c69b709e7a2338c316c50382ba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 18 Mar 2020 02:50:39 +0100 Subject: [PATCH 227/243] clean up a few lint docs --- clippy_lints/src/approx_const.rs | 6 +++--- clippy_lints/src/assertions_on_constants.rs | 4 +--- clippy_lints/src/block_in_if_condition.rs | 2 +- clippy_lints/src/needless_bool.rs | 8 +++++++- clippy_lints/src/swap.rs | 2 +- clippy_lints/src/types.rs | 2 +- 6 files changed, 14 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 0e497e175d66..7e6e2c7eaebe 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -23,11 +23,11 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// // Bad /// let x = 3.14; /// let y = 1_f64 / x; - /// - /// // Good + /// ``` + /// Use predefined constants instead: + /// ```rust /// let x = std::f32::consts::PI; /// let y = std::f64::consts::FRAC_1_PI; /// ``` diff --git a/clippy_lints/src/assertions_on_constants.rs b/clippy_lints/src/assertions_on_constants.rs index bd9a2a7c40c4..e2fe5f2400f4 100644 --- a/clippy_lints/src/assertions_on_constants.rs +++ b/clippy_lints/src/assertions_on_constants.rs @@ -11,16 +11,14 @@ declare_clippy_lint! { /// **What it does:** Checks for `assert!(true)` and `assert!(false)` calls. /// /// **Why is this bad?** Will be optimized out by the compiler or should probably be replaced by a - /// panic!() or unreachable!() + /// `panic!()` or `unreachable!()` /// /// **Known problems:** None /// /// **Example:** /// ```rust,ignore /// assert!(false) - /// // or /// assert!(true) - /// // or /// const B: bool = false; /// assert!(B) /// ``` diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 56b4e5522f4e..50c1262f2d6d 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -35,7 +35,7 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```ignore + /// ```rust,ignore /// if { let x = somefunc(); x } {} /// // or /// if somefunc(|x| { x == 47 }) {} diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 4c00d15538ff..19c22d2b791c 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -51,7 +51,13 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust,ignore - /// if x == true {} // could be `if x { }` + /// if x == true {} + /// if y == false {} + /// ``` + /// use `x` directly: + /// ```rust,ignore + /// if x {} + /// if !y {} /// ``` pub BOOL_COMPARISON, complexity, diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index a1f5dee2a9c3..05428f1a31fb 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -54,7 +54,7 @@ declare_clippy_lint! { /// a = b; /// b = a; /// ``` - /// Could be written as: + /// If swapping is intended, use `swap()` instead: /// ```rust /// # let mut a = 1; /// # let mut b = 2; diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 26d425cf2416..d466924dc689 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1642,7 +1642,7 @@ declare_clippy_lint! { /// **Example:** /// /// ```rust - /// let vec: Vec = vec![]; + /// let vec: Vec = Vec::new(); /// if vec.len() <= 0 {} /// if 100 > std::i32::MAX {} /// ``` From b875c53d2c23329a6148d9d6bb90522abd11df7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 18 Mar 2020 03:27:05 +0100 Subject: [PATCH 228/243] rustup https://github.com/rust-lang/rust/pull/69189 rustups https://github.com/rust-lang/rust/pull/69189 which is part of https://github.com/rust-lang/rust/pull/70085 (at least I think this is the only pr that changes clippy test stdout) --- tests/ui/inefficient_to_string.stderr | 8 ++++---- tests/ui/transmute.stderr | 2 +- tests/ui/transmute_ptr_to_ptr.stderr | 28 ++++++++++++++++++++++++++- tests/ui/transmute_ptr_to_ref.stderr | 4 ++-- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/tests/ui/inefficient_to_string.stderr b/tests/ui/inefficient_to_string.stderr index 1c0490ffa44c..4be46161e8b7 100644 --- a/tests/ui/inefficient_to_string.stderr +++ b/tests/ui/inefficient_to_string.stderr @@ -35,21 +35,21 @@ LL | let _: String = rrrstring.to_string(); | = help: `&&std::string::String` implements `ToString` through a slower blanket impl, but `std::string::String` has a fast specialization of `ToString` -error: calling `to_string` on `&&std::borrow::Cow<'_, str>` +error: calling `to_string` on `&&std::borrow::Cow` --> $DIR/inefficient_to_string.rs:29:21 | LL | let _: String = rrcow.to_string(); | ^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(*rrcow).to_string()` | - = help: `&std::borrow::Cow<'_, str>` implements `ToString` through a slower blanket impl, but `std::borrow::Cow<'_, str>` has a fast specialization of `ToString` + = help: `&std::borrow::Cow` implements `ToString` through a slower blanket impl, but `std::borrow::Cow` has a fast specialization of `ToString` -error: calling `to_string` on `&&&std::borrow::Cow<'_, str>` +error: calling `to_string` on `&&&std::borrow::Cow` --> $DIR/inefficient_to_string.rs:30:21 | LL | let _: String = rrrcow.to_string(); | ^^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(**rrrcow).to_string()` | - = help: `&&std::borrow::Cow<'_, str>` implements `ToString` through a slower blanket impl, but `std::borrow::Cow<'_, str>` has a fast specialization of `ToString` + = help: `&&std::borrow::Cow` implements `ToString` through a slower blanket impl, but `std::borrow::Cow` has a fast specialization of `ToString` error: aborting due to 6 previous errors diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index 37162ecf4756..8582080498f3 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -1,4 +1,4 @@ -error: transmute from a type (`&'a T`) to itself +error: transmute from a type (`&T`) to itself --> $DIR/transmute.rs:19:20 | LL | let _: &'a T = core::intrinsics::transmute(t); diff --git a/tests/ui/transmute_ptr_to_ptr.stderr b/tests/ui/transmute_ptr_to_ptr.stderr index 4d1b8fcc199e..61fbea1c164e 100644 --- a/tests/ui/transmute_ptr_to_ptr.stderr +++ b/tests/ui/transmute_ptr_to_ptr.stderr @@ -1,3 +1,17 @@ +error: transmute from a type (`&T`) to itself + --> $DIR/transmute_ptr_to_ptr.rs:8:5 + | +LL | std::mem::transmute::<&'a T, &'static T>(t) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::useless-transmute` implied by `-D warnings` + +error: transmute from a type (`&T`) to itself + --> $DIR/transmute_ptr_to_ptr.rs:13:5 + | +LL | std::mem::transmute::<&'a T, &'b T>(t) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: transmute from a pointer to a pointer --> $DIR/transmute_ptr_to_ptr.rs:29:29 | @@ -36,5 +50,17 @@ error: transmute from a reference to a reference LL | let _: &GenericParam = std::mem::transmute(&GenericParam { t: 1u32 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam as *const GenericParam)` -error: aborting due to 6 previous errors +error: transmute from a type (`&LifetimeParam`) to itself + --> $DIR/transmute_ptr_to_ptr.rs:50:47 + | +LL | let _: &LifetimeParam<'static> = unsafe { std::mem::transmute(&lp) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: transmute from a type (`&GenericParam<&LifetimeParam>`) to itself + --> $DIR/transmute_ptr_to_ptr.rs:51:62 + | +LL | let _: &GenericParam<&LifetimeParam<'static>> = unsafe { std::mem::transmute(&GenericParam { t: &lp }) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 10 previous errors diff --git a/tests/ui/transmute_ptr_to_ref.stderr b/tests/ui/transmute_ptr_to_ref.stderr index 2d52e421816e..df0598a58cd3 100644 --- a/tests/ui/transmute_ptr_to_ref.stderr +++ b/tests/ui/transmute_ptr_to_ref.stderr @@ -42,13 +42,13 @@ error: transmute from a pointer type (`*mut U`) to a reference type (`&T`) LL | let _: &T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)` -error: transmute from a pointer type (`*const i32`) to a reference type (`&issue1231::Foo<'_, u8>`) +error: transmute from a pointer type (`*const i32`) to a reference type (`&issue1231::Foo`) --> $DIR/transmute_ptr_to_ref.rs:32:32 | LL | let _: &Foo = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const Foo<_>)` -error: transmute from a pointer type (`*const i32`) to a reference type (`&issue1231::Foo<'_, &u8>`) +error: transmute from a pointer type (`*const i32`) to a reference type (`&issue1231::Foo<&u8>`) --> $DIR/transmute_ptr_to_ref.rs:34:33 | LL | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; From c7c7ab23aac80e9615e6b1112c111ef6f3984e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Tue, 17 Mar 2020 23:32:30 +0100 Subject: [PATCH 229/243] integer_arithmetic: detect integer arithmetic on references. Also fixes the same for float_arithmetic. changelog: integer_arithmetic,float_arithmetic: fix false negatives with references on integers Fixes #5328 --- clippy_lints/src/arithmetic.rs | 5 +- tests/ui/arithmetic.rs | 55 +++++++++++++- tests/ui/arithmetic.stderr | 126 +++++++++++++++++++++++++++------ 3 files changed, 162 insertions(+), 24 deletions(-) diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index fd252b9ee109..a138c9d3545c 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -81,11 +81,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { | hir::BinOpKind::Gt => return, _ => (), } + let (l_ty, r_ty) = (cx.tables.expr_ty(l), cx.tables.expr_ty(r)); - if l_ty.is_integral() && r_ty.is_integral() { + if l_ty.peel_refs().is_integral() && r_ty.peel_refs().is_integral() { span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); self.expr_span = Some(expr.span); - } else if l_ty.is_floating_point() && r_ty.is_floating_point() { + } else if l_ty.peel_refs().is_floating_point() && r_ty.peel_refs().is_floating_point() { span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected"); self.expr_span = Some(expr.span); } diff --git a/tests/ui/arithmetic.rs b/tests/ui/arithmetic.rs index dc11cbd98deb..38892f6b14de 100644 --- a/tests/ui/arithmetic.rs +++ b/tests/ui/arithmetic.rs @@ -4,7 +4,9 @@ clippy::shadow_reuse, clippy::shadow_unrelated, clippy::no_effect, - clippy::unnecessary_operation + clippy::unnecessary_operation, + clippy::op_ref, + clippy::trivially_copy_pass_by_ref )] #[rustfmt::skip] @@ -90,4 +92,55 @@ fn main() { 1 + 1 }; } + + +} + +// warn on references as well! (#5328) +pub fn int_arith_ref() { + 3 + &1; + &3 + 1; + &3 + &1; +} + +pub fn foo(x: &i32) -> i32 { + let a = 5; + a + x +} + +pub fn bar(x: &i32, y: &i32) -> i32 { + x + y +} + +pub fn baz(x: i32, y: &i32) -> i32 { + x + y +} + +pub fn qux(x: i32, y: i32) -> i32 { + (&x + &y) +} + +// also warn about floating point arith with references involved + +pub fn float_arith_ref() { + 3.1_f32 + &1.2_f32; + &3.4_f32 + 1.5_f32; + &3.5_f32 + &1.3_f32; +} + +pub fn float_foo(f: &f32) -> f32 { + let a = 5.1; + a + f +} + +pub fn float_bar(f1: &f32, f2: &f32) -> f32 { + f1 + f2 +} + +pub fn float_baz(f1: f32, f2: &f32) -> f32 { + f1 + f2 +} + +pub fn float_qux(f1: f32, f2: f32) -> f32 { + (&f1 + &f2) } diff --git a/tests/ui/arithmetic.stderr b/tests/ui/arithmetic.stderr index d999b69d7cbb..5de2eecf128d 100644 --- a/tests/ui/arithmetic.stderr +++ b/tests/ui/arithmetic.stderr @@ -1,5 +1,5 @@ error: integer arithmetic detected - --> $DIR/arithmetic.rs:13:5 + --> $DIR/arithmetic.rs:15:5 | LL | 1 + i; | ^^^^^ @@ -7,62 +7,62 @@ LL | 1 + i; = note: `-D clippy::integer-arithmetic` implied by `-D warnings` error: integer arithmetic detected - --> $DIR/arithmetic.rs:14:5 + --> $DIR/arithmetic.rs:16:5 | LL | i * 2; | ^^^^^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:15:5 + --> $DIR/arithmetic.rs:17:5 | LL | / 1 % LL | | i / 2; // no error, this is part of the expression in the preceding line | |_________^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:17:5 + --> $DIR/arithmetic.rs:19:5 | LL | i - 2 + 2 - i; | ^^^^^^^^^^^^^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:18:5 + --> $DIR/arithmetic.rs:20:5 | LL | -i; | ^^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:30:5 + --> $DIR/arithmetic.rs:32:5 | LL | i += 1; | ^^^^^^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:31:5 + --> $DIR/arithmetic.rs:33:5 | LL | i -= 1; | ^^^^^^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:32:5 + --> $DIR/arithmetic.rs:34:5 | LL | i *= 2; | ^^^^^^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:33:5 + --> $DIR/arithmetic.rs:35:5 | LL | i /= 2; | ^^^^^^ error: integer arithmetic detected - --> $DIR/arithmetic.rs:34:5 + --> $DIR/arithmetic.rs:36:5 | LL | i %= 2; | ^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:45:5 + --> $DIR/arithmetic.rs:47:5 | LL | f * 2.0; | ^^^^^^^ @@ -70,58 +70,142 @@ LL | f * 2.0; = note: `-D clippy::float-arithmetic` implied by `-D warnings` error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:47:5 + --> $DIR/arithmetic.rs:49:5 | LL | 1.0 + f; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:48:5 + --> $DIR/arithmetic.rs:50:5 | LL | f * 2.0; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:49:5 + --> $DIR/arithmetic.rs:51:5 | LL | f / 2.0; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:50:5 + --> $DIR/arithmetic.rs:52:5 | LL | f - 2.0 * 4.2; | ^^^^^^^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:51:5 + --> $DIR/arithmetic.rs:53:5 | LL | -f; | ^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:53:5 + --> $DIR/arithmetic.rs:55:5 | LL | f += 1.0; | ^^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:54:5 + --> $DIR/arithmetic.rs:56:5 | LL | f -= 1.0; | ^^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:55:5 + --> $DIR/arithmetic.rs:57:5 | LL | f *= 2.0; | ^^^^^^^^ error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:56:5 + --> $DIR/arithmetic.rs:58:5 | LL | f /= 2.0; | ^^^^^^^^ -error: aborting due to 20 previous errors +error: integer arithmetic detected + --> $DIR/arithmetic.rs:101:5 + | +LL | 3 + &1; + | ^^^^^^ + +error: integer arithmetic detected + --> $DIR/arithmetic.rs:102:5 + | +LL | &3 + 1; + | ^^^^^^ + +error: integer arithmetic detected + --> $DIR/arithmetic.rs:103:5 + | +LL | &3 + &1; + | ^^^^^^^ + +error: integer arithmetic detected + --> $DIR/arithmetic.rs:108:5 + | +LL | a + x + | ^^^^^ + +error: integer arithmetic detected + --> $DIR/arithmetic.rs:112:5 + | +LL | x + y + | ^^^^^ + +error: integer arithmetic detected + --> $DIR/arithmetic.rs:116:5 + | +LL | x + y + | ^^^^^ + +error: integer arithmetic detected + --> $DIR/arithmetic.rs:120:5 + | +LL | (&x + &y) + | ^^^^^^^^^ + +error: floating-point arithmetic detected + --> $DIR/arithmetic.rs:126:5 + | +LL | 3.1_f32 + &1.2_f32; + | ^^^^^^^^^^^^^^^^^^ + +error: floating-point arithmetic detected + --> $DIR/arithmetic.rs:127:5 + | +LL | &3.4_f32 + 1.5_f32; + | ^^^^^^^^^^^^^^^^^^ + +error: floating-point arithmetic detected + --> $DIR/arithmetic.rs:128:5 + | +LL | &3.5_f32 + &1.3_f32; + | ^^^^^^^^^^^^^^^^^^^ + +error: floating-point arithmetic detected + --> $DIR/arithmetic.rs:133:5 + | +LL | a + f + | ^^^^^ + +error: floating-point arithmetic detected + --> $DIR/arithmetic.rs:137:5 + | +LL | f1 + f2 + | ^^^^^^^ + +error: floating-point arithmetic detected + --> $DIR/arithmetic.rs:141:5 + | +LL | f1 + f2 + | ^^^^^^^ + +error: floating-point arithmetic detected + --> $DIR/arithmetic.rs:145:5 + | +LL | (&f1 + &f2) + | ^^^^^^^^^^^ + +error: aborting due to 34 previous errors From 552768f092d3dcc1f39858d9a81707156df32102 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 18 Mar 2020 14:49:40 +0100 Subject: [PATCH 230/243] Update changelog to 1.43.0 beta --- CHANGELOG.md | 97 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 63 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8d41e3b31d2..87d6339d6032 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,31 +6,21 @@ document. ## Unreleased / In Rust Beta or Nightly -[69f99e7...master](https://github.com/rust-lang/rust-clippy/compare/69f99e7...master) +[329923e...master](https://github.com/rust-lang/rust-clippy/compare/329923e...master) -## Rust 1.42 +## Rust 1.43 -Current Beta +Current beta, release 2020-04-23 -[69f99e7...329923e](https://github.com/rust-lang/rust-clippy/compare/69f99e7...329923e) +[4ee1206...329923e](https://github.com/rust-lang/rust-clippy/compare/4ee1206...329923e) ### New lints -* [`filetype_is_file`] [#4543](https://github.com/rust-lang/rust-clippy/pull/4543) -* [`let_underscore_must_use`] [#4823](https://github.com/rust-lang/rust-clippy/pull/4823) -* [`modulo_arithmetic`] [#4867](https://github.com/rust-lang/rust-clippy/pull/4867) -* [`mem_replace_with_default`] [#4881](https://github.com/rust-lang/rust-clippy/pull/4881) -* [`mutable_key_type`] [#4885](https://github.com/rust-lang/rust-clippy/pull/4885) * [`imprecise_flops`] [#4897](https://github.com/rust-lang/rust-clippy/pull/4897) * [`suboptimal_flops`] [#4897](https://github.com/rust-lang/rust-clippy/pull/4897) -* [`option_as_ref_deref`] [#4945](https://github.com/rust-lang/rust-clippy/pull/4945) -* [`wildcard_in_or_patterns`] [#4960](https://github.com/rust-lang/rust-clippy/pull/4960) -* [`iter_nth_zero`] [#4966](https://github.com/rust-lang/rust-clippy/pull/4966) -* [`invalid_atomic_ordering`] [#4999](https://github.com/rust-lang/rust-clippy/pull/4999) * [`wildcard_imports`] [#5029](https://github.com/rust-lang/rust-clippy/pull/5029) * [`single_component_path_imports`] [#5058](https://github.com/rust-lang/rust-clippy/pull/5058) * [`match_single_binding`] [#5061](https://github.com/rust-lang/rust-clippy/pull/5061) -* [`skip_while_next`] [#5067](https://github.com/rust-lang/rust-clippy/pull/5067) * [`let_underscore_lock`] [#5101](https://github.com/rust-lang/rust-clippy/pull/5101) * [`struct_excessive_bools`] [#5125](https://github.com/rust-lang/rust-clippy/pull/5125) * [`fn_params_excessive_bools`] [#5125](https://github.com/rust-lang/rust-clippy/pull/5125) @@ -40,10 +30,66 @@ Current Beta ### Moves and Deprecations +* Move [`unneeded_field_pattern`] to pedantic group [#5200](https://github.com/rust-lang/rust-clippy/pull/5200) + +### Enhancements + +* Make [`missing_errors_doc`] lint also trigger on `async` functions + [#5181](https://github.com/rust-lang/rust-clippy/pull/5181) +* Add more constants to [`approx_constant`] [#5193](https://github.com/rust-lang/rust-clippy/pull/5193) +* Extend [`question_mark`] lint [#5266](https://github.com/rust-lang/rust-clippy/pull/5266) + +### False Positive Fixes + +* [`use_debug`] [#5047](https://github.com/rust-lang/rust-clippy/pull/5047) +* [`unnecessary_unwrap`] [#5132](https://github.com/rust-lang/rust-clippy/pull/5132) +* [`zero_prefixed_literal`] [#5170](https://github.com/rust-lang/rust-clippy/pull/5170) +* [`missing_const_for_fn`] [#5216](https://github.com/rust-lang/rust-clippy/pull/5216) + +### Suggestion Improvements + +* Improve suggestion when blocks of code are suggested [#5134](https://github.com/rust-lang/rust-clippy/pull/5134) + +### ICE Fixes + +* `misc_early` lints [#5129](https://github.com/rust-lang/rust-clippy/pull/5129) +* [`missing_errors_doc`] [#5213](https://github.com/rust-lang/rust-clippy/pull/5213) +* Fix ICE when evaluating `usize`s [#5256](https://github.com/rust-lang/rust-clippy/pull/5256) + +### Documentation + +* Improve documentation of [`iter_nth_zero`] +* Add documentation pages for stable releases [#5171](https://github.com/rust-lang/rust-clippy/pull/5171) + +### Others + +* Clippy now completely runs on GitHub Actions [#5190](https://github.com/rust-lang/rust-clippy/pull/5190) + + +## Rust 1.42 + +Current stable, released 2020-03-12 + +[69f99e7...4ee1206](https://github.com/rust-lang/rust-clippy/compare/69f99e7...4ee1206) + +### New lints + +* [`filetype_is_file`] [#4543](https://github.com/rust-lang/rust-clippy/pull/4543) +* [`let_underscore_must_use`] [#4823](https://github.com/rust-lang/rust-clippy/pull/4823) +* [`modulo_arithmetic`] [#4867](https://github.com/rust-lang/rust-clippy/pull/4867) +* [`mem_replace_with_default`] [#4881](https://github.com/rust-lang/rust-clippy/pull/4881) +* [`mutable_key_type`] [#4885](https://github.com/rust-lang/rust-clippy/pull/4885) +* [`option_as_ref_deref`] [#4945](https://github.com/rust-lang/rust-clippy/pull/4945) +* [`wildcard_in_or_patterns`] [#4960](https://github.com/rust-lang/rust-clippy/pull/4960) +* [`iter_nth_zero`] [#4966](https://github.com/rust-lang/rust-clippy/pull/4966) +* [`invalid_atomic_ordering`] [#4999](https://github.com/rust-lang/rust-clippy/pull/4999) +* [`skip_while_next`] [#5067](https://github.com/rust-lang/rust-clippy/pull/5067) + +### Moves and Deprecations + * Move [`transmute_float_to_int`] from nursery to complexity group [#5015](https://github.com/rust-lang/rust-clippy/pull/5015) * Move [`range_plus_one`] to pedantic group [#5057](https://github.com/rust-lang/rust-clippy/pull/5057) -* Move [`unneeded_field_pattern`] to pedantic group [#5200](https://github.com/rust-lang/rust-clippy/pull/5200) * Move [`debug_assert_with_mut_call`] to nursery group [#5106](https://github.com/rust-lang/rust-clippy/pull/5106) * Deprecate [`unused_label`] [#4930](https://github.com/rust-lang/rust-clippy/pull/4930) @@ -51,10 +97,6 @@ Current Beta * Lint vectored IO in [`unused_io_amount`] [#5027](https://github.com/rust-lang/rust-clippy/pull/5027) * Make [`vec_box`] configurable by adding a size threshold [#5081](https://github.com/rust-lang/rust-clippy/pull/5081) -* Make [`missing_errors_doc`] lint also trigger an `async` functions - [#5181](https://github.com/rust-lang/rust-clippy/pull/5181) -* Add more constants to [`approx_constant`] [#5193](https://github.com/rust-lang/rust-clippy/pull/5193) -* Extend [`question_mark`] lint [#5266](https://github.com/rust-lang/rust-clippy/pull/5266) * Also lint constants in [`cmp_nan`] [#4910](https://github.com/rust-lang/rust-clippy/pull/4910) * Fix false negative in [`expect_fun_call`] [#4915](https://github.com/rust-lang/rust-clippy/pull/4915) * Fix false negative in [`redundant_clone`] [#5017](https://github.com/rust-lang/rust-clippy/pull/5017) @@ -64,13 +106,9 @@ Current Beta * [`map_clone`] [#4937](https://github.com/rust-lang/rust-clippy/pull/4937) * [`replace_consts`] [#4977](https://github.com/rust-lang/rust-clippy/pull/4977) * [`let_and_return`] [#5008](https://github.com/rust-lang/rust-clippy/pull/5008) -* [`use_debug`] [#5047](https://github.com/rust-lang/rust-clippy/pull/5047) * [`eq_op`] [#5079](https://github.com/rust-lang/rust-clippy/pull/5079) * [`possible_missing_comma`] [#5083](https://github.com/rust-lang/rust-clippy/pull/5083) * [`debug_assert_with_mut_call`] [#5106](https://github.com/rust-lang/rust-clippy/pull/5106) -* [`unnecessary_unwrap`] [#5132](https://github.com/rust-lang/rust-clippy/pull/5132) -* [`zero_prefixed_literal`] [#5170](https://github.com/rust-lang/rust-clippy/pull/5170) -* [`missing_const_for_fn`] [#5216](https://github.com/rust-lang/rust-clippy/pull/5216) * Don't trigger [`let_underscore_must_use`] in external macros [#5082](https://github.com/rust-lang/rust-clippy/pull/5082) * Don't trigger [`empty_loop`] in `no_std` crates [#5086](https://github.com/rust-lang/rust-clippy/pull/5086) @@ -85,28 +123,19 @@ Current Beta * [`explicit_into_iter_loop`] [#4978](https://github.com/rust-lang/rust-clippy/pull/4978) * [`useless_attribute`] [#5022](https://github.com/rust-lang/rust-clippy/pull/5022) * [`if_let_some_result`] [#5032](https://github.com/rust-lang/rust-clippy/pull/5032) -* Improve suggestion when blocks of code are suggested [#5134](https://github.com/rust-lang/rust-clippy/pull/5134) ### ICE fixes * [`unsound_collection_transmute`] [#4975](https://github.com/rust-lang/rust-clippy/pull/4975) -* `misc_early` lints [#5129](https://github.com/rust-lang/rust-clippy/pull/5129) -* [`missing_errors_doc`] [#5213](https://github.com/rust-lang/rust-clippy/pull/5213) -* Fix ICE when evaluating `usize`s [#5256](https://github.com/rust-lang/rust-clippy/pull/5256) ### Documentation -* Improve documentation of `empty_enum`, `replace_consts`, `redundant_clone`, and `iterator_step_by_zero` -* Add documentation pages for stable releases [#5171](https://github.com/rust-lang/rust-clippy/pull/5171) - -### Others - -* Clippy now completely runs on GitHub Actions [#5190](https://github.com/rust-lang/rust-clippy/pull/5190) +* Improve documentation of [`empty_enum`], [`replace_consts`], [`redundant_clone`], and [`iterator_step_by_zero`] ## Rust 1.41 -Current stable, released 2020-01-30 +Released 2020-01-30 [c8e3cfb...69f99e7](https://github.com/rust-lang/rust-clippy/compare/c8e3cfb...69f99e7) From a808779441bc6fdd6ea4c78366229d5c660d6abf Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 18 Mar 2020 15:24:48 +0100 Subject: [PATCH 231/243] Split up checked_unwrap test further --- .../ui/checked_unwrap/complex_conditionals.rs | 11 ------- .../complex_conditionals.stderr | 19 +----------- .../complex_conditionals_nested.rs | 15 +++++++++ .../complex_conditionals_nested.stderr | 31 +++++++++++++++++++ 4 files changed, 47 insertions(+), 29 deletions(-) create mode 100644 tests/ui/checked_unwrap/complex_conditionals_nested.rs create mode 100644 tests/ui/checked_unwrap/complex_conditionals_nested.stderr diff --git a/tests/ui/checked_unwrap/complex_conditionals.rs b/tests/ui/checked_unwrap/complex_conditionals.rs index fbeee1b572a6..c986c992a07a 100644 --- a/tests/ui/checked_unwrap/complex_conditionals.rs +++ b/tests/ui/checked_unwrap/complex_conditionals.rs @@ -51,15 +51,4 @@ fn test_complex_conditions() { } } -fn test_nested() { - fn nested() { - let x = Some(()); - if x.is_some() { - x.unwrap(); // unnecessary - } else { - x.unwrap(); // will panic - } - } -} - fn main() {} diff --git a/tests/ui/checked_unwrap/complex_conditionals.stderr b/tests/ui/checked_unwrap/complex_conditionals.stderr index 4e53bd769e27..dc666bab4603 100644 --- a/tests/ui/checked_unwrap/complex_conditionals.stderr +++ b/tests/ui/checked_unwrap/complex_conditionals.stderr @@ -188,22 +188,5 @@ LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { LL | z.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ -error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/complex_conditionals.rs:58:13 - | -LL | if x.is_some() { - | ----------- the check is happening here -LL | x.unwrap(); // unnecessary - | ^^^^^^^^^^ - -error: This call to `unwrap()` will always panic. - --> $DIR/complex_conditionals.rs:60:13 - | -LL | if x.is_some() { - | ----------- because of this check -... -LL | x.unwrap(); // will panic - | ^^^^^^^^^^ - -error: aborting due to 22 previous errors +error: aborting due to 20 previous errors diff --git a/tests/ui/checked_unwrap/complex_conditionals_nested.rs b/tests/ui/checked_unwrap/complex_conditionals_nested.rs new file mode 100644 index 000000000000..2307996a48ff --- /dev/null +++ b/tests/ui/checked_unwrap/complex_conditionals_nested.rs @@ -0,0 +1,15 @@ +#![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] +#![allow(clippy::if_same_then_else)] + +fn test_nested() { + fn nested() { + let x = Some(()); + if x.is_some() { + x.unwrap(); // unnecessary + } else { + x.unwrap(); // will panic + } + } +} + +fn main() {} diff --git a/tests/ui/checked_unwrap/complex_conditionals_nested.stderr b/tests/ui/checked_unwrap/complex_conditionals_nested.stderr new file mode 100644 index 000000000000..e4d085470c3b --- /dev/null +++ b/tests/ui/checked_unwrap/complex_conditionals_nested.stderr @@ -0,0 +1,31 @@ +error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/complex_conditionals_nested.rs:8:13 + | +LL | if x.is_some() { + | ----------- the check is happening here +LL | x.unwrap(); // unnecessary + | ^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/complex_conditionals_nested.rs:1:35 + | +LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: This call to `unwrap()` will always panic. + --> $DIR/complex_conditionals_nested.rs:10:13 + | +LL | if x.is_some() { + | ----------- because of this check +... +LL | x.unwrap(); // will panic + | ^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/complex_conditionals_nested.rs:1:9 + | +LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From f041dcdb4e47b01e5a22f86054ad57d42ed17f4a Mon Sep 17 00:00:00 2001 From: flip1995 Date: Wed, 18 Mar 2020 15:27:25 +0100 Subject: [PATCH 232/243] Fix limit-stderr-files test --- clippy_dev/src/stderr_length_check.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/clippy_dev/src/stderr_length_check.rs b/clippy_dev/src/stderr_length_check.rs index 041ee6911377..c511733f7bf4 100644 --- a/clippy_dev/src/stderr_length_check.rs +++ b/clippy_dev/src/stderr_length_check.rs @@ -4,6 +4,8 @@ use std::path::{Path, PathBuf}; use walkdir::WalkDir; +use clippy_dev::clippy_project_root; + // The maximum length allowed for stderr files. // // We limit this because small files are easier to deal with than bigger files. @@ -14,22 +16,24 @@ pub fn check() { if !exceeding_files.is_empty() { eprintln!("Error: stderr files exceeding limit of {} lines:", LENGTH_LIMIT); - for path in exceeding_files { - println!("{}", path.display()); + for (path, count) in exceeding_files { + println!("{}: {}", path.display(), count); } std::process::exit(1); } } -fn exceeding_stderr_files() -> Vec { +fn exceeding_stderr_files() -> Vec<(PathBuf, usize)> { // We use `WalkDir` instead of `fs::read_dir` here in order to recurse into subdirectories. - WalkDir::new("../tests/ui") + WalkDir::new(clippy_project_root().join("tests/ui")) .into_iter() .filter_map(Result::ok) + .filter(|f| !f.file_type().is_dir()) .filter_map(|e| { let p = e.into_path(); - if p.extension() == Some(OsStr::new("stderr")) && count_linenumbers(&p) > LENGTH_LIMIT { - Some(p) + let count = count_linenumbers(&p); + if p.extension() == Some(OsStr::new("stderr")) && count > LENGTH_LIMIT { + Some((p, count)) } else { None } From ec1dcde46b44b4fb6fabf4a5e0fc43dcb4277bb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 18 Mar 2020 15:41:42 +0100 Subject: [PATCH 233/243] tests: arithmetic: split into integer_arithmetic and float_arithmetic files. --- tests/ui/arithmetic.stderr | 211 ------------------ tests/ui/float_arithmetic.rs | 53 +++++ tests/ui/float_arithmetic.stderr | 106 +++++++++ .../{arithmetic.rs => integer_arithmetic.rs} | 44 ---- tests/ui/integer_arithmetic.stderr | 107 +++++++++ 5 files changed, 266 insertions(+), 255 deletions(-) delete mode 100644 tests/ui/arithmetic.stderr create mode 100644 tests/ui/float_arithmetic.rs create mode 100644 tests/ui/float_arithmetic.stderr rename tests/ui/{arithmetic.rs => integer_arithmetic.rs} (71%) create mode 100644 tests/ui/integer_arithmetic.stderr diff --git a/tests/ui/arithmetic.stderr b/tests/ui/arithmetic.stderr deleted file mode 100644 index 5de2eecf128d..000000000000 --- a/tests/ui/arithmetic.stderr +++ /dev/null @@ -1,211 +0,0 @@ -error: integer arithmetic detected - --> $DIR/arithmetic.rs:15:5 - | -LL | 1 + i; - | ^^^^^ - | - = note: `-D clippy::integer-arithmetic` implied by `-D warnings` - -error: integer arithmetic detected - --> $DIR/arithmetic.rs:16:5 - | -LL | i * 2; - | ^^^^^ - -error: integer arithmetic detected - --> $DIR/arithmetic.rs:17:5 - | -LL | / 1 % -LL | | i / 2; // no error, this is part of the expression in the preceding line - | |_________^ - -error: integer arithmetic detected - --> $DIR/arithmetic.rs:19:5 - | -LL | i - 2 + 2 - i; - | ^^^^^^^^^^^^^ - -error: integer arithmetic detected - --> $DIR/arithmetic.rs:20:5 - | -LL | -i; - | ^^ - -error: integer arithmetic detected - --> $DIR/arithmetic.rs:32:5 - | -LL | i += 1; - | ^^^^^^ - -error: integer arithmetic detected - --> $DIR/arithmetic.rs:33:5 - | -LL | i -= 1; - | ^^^^^^ - -error: integer arithmetic detected - --> $DIR/arithmetic.rs:34:5 - | -LL | i *= 2; - | ^^^^^^ - -error: integer arithmetic detected - --> $DIR/arithmetic.rs:35:5 - | -LL | i /= 2; - | ^^^^^^ - -error: integer arithmetic detected - --> $DIR/arithmetic.rs:36:5 - | -LL | i %= 2; - | ^^^^^^ - -error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:47:5 - | -LL | f * 2.0; - | ^^^^^^^ - | - = note: `-D clippy::float-arithmetic` implied by `-D warnings` - -error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:49:5 - | -LL | 1.0 + f; - | ^^^^^^^ - -error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:50:5 - | -LL | f * 2.0; - | ^^^^^^^ - -error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:51:5 - | -LL | f / 2.0; - | ^^^^^^^ - -error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:52:5 - | -LL | f - 2.0 * 4.2; - | ^^^^^^^^^^^^^ - -error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:53:5 - | -LL | -f; - | ^^ - -error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:55:5 - | -LL | f += 1.0; - | ^^^^^^^^ - -error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:56:5 - | -LL | f -= 1.0; - | ^^^^^^^^ - -error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:57:5 - | -LL | f *= 2.0; - | ^^^^^^^^ - -error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:58:5 - | -LL | f /= 2.0; - | ^^^^^^^^ - -error: integer arithmetic detected - --> $DIR/arithmetic.rs:101:5 - | -LL | 3 + &1; - | ^^^^^^ - -error: integer arithmetic detected - --> $DIR/arithmetic.rs:102:5 - | -LL | &3 + 1; - | ^^^^^^ - -error: integer arithmetic detected - --> $DIR/arithmetic.rs:103:5 - | -LL | &3 + &1; - | ^^^^^^^ - -error: integer arithmetic detected - --> $DIR/arithmetic.rs:108:5 - | -LL | a + x - | ^^^^^ - -error: integer arithmetic detected - --> $DIR/arithmetic.rs:112:5 - | -LL | x + y - | ^^^^^ - -error: integer arithmetic detected - --> $DIR/arithmetic.rs:116:5 - | -LL | x + y - | ^^^^^ - -error: integer arithmetic detected - --> $DIR/arithmetic.rs:120:5 - | -LL | (&x + &y) - | ^^^^^^^^^ - -error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:126:5 - | -LL | 3.1_f32 + &1.2_f32; - | ^^^^^^^^^^^^^^^^^^ - -error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:127:5 - | -LL | &3.4_f32 + 1.5_f32; - | ^^^^^^^^^^^^^^^^^^ - -error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:128:5 - | -LL | &3.5_f32 + &1.3_f32; - | ^^^^^^^^^^^^^^^^^^^ - -error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:133:5 - | -LL | a + f - | ^^^^^ - -error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:137:5 - | -LL | f1 + f2 - | ^^^^^^^ - -error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:141:5 - | -LL | f1 + f2 - | ^^^^^^^ - -error: floating-point arithmetic detected - --> $DIR/arithmetic.rs:145:5 - | -LL | (&f1 + &f2) - | ^^^^^^^^^^^ - -error: aborting due to 34 previous errors - diff --git a/tests/ui/float_arithmetic.rs b/tests/ui/float_arithmetic.rs new file mode 100644 index 000000000000..5ad320c62095 --- /dev/null +++ b/tests/ui/float_arithmetic.rs @@ -0,0 +1,53 @@ +#![warn(clippy::integer_arithmetic, clippy::float_arithmetic)] +#![allow( + unused, + clippy::shadow_reuse, + clippy::shadow_unrelated, + clippy::no_effect, + clippy::unnecessary_operation, + clippy::op_ref, + clippy::trivially_copy_pass_by_ref +)] + +#[rustfmt::skip] +fn main() { + let mut f = 1.0f32; + + f * 2.0; + + 1.0 + f; + f * 2.0; + f / 2.0; + f - 2.0 * 4.2; + -f; + + f += 1.0; + f -= 1.0; + f *= 2.0; + f /= 2.0; +} + +// also warn about floating point arith with references involved + +pub fn float_arith_ref() { + 3.1_f32 + &1.2_f32; + &3.4_f32 + 1.5_f32; + &3.5_f32 + &1.3_f32; +} + +pub fn float_foo(f: &f32) -> f32 { + let a = 5.1; + a + f +} + +pub fn float_bar(f1: &f32, f2: &f32) -> f32 { + f1 + f2 +} + +pub fn float_baz(f1: f32, f2: &f32) -> f32 { + f1 + f2 +} + +pub fn float_qux(f1: f32, f2: f32) -> f32 { + (&f1 + &f2) +} diff --git a/tests/ui/float_arithmetic.stderr b/tests/ui/float_arithmetic.stderr new file mode 100644 index 000000000000..809392529fd9 --- /dev/null +++ b/tests/ui/float_arithmetic.stderr @@ -0,0 +1,106 @@ +error: floating-point arithmetic detected + --> $DIR/float_arithmetic.rs:16:5 + | +LL | f * 2.0; + | ^^^^^^^ + | + = note: `-D clippy::float-arithmetic` implied by `-D warnings` + +error: floating-point arithmetic detected + --> $DIR/float_arithmetic.rs:18:5 + | +LL | 1.0 + f; + | ^^^^^^^ + +error: floating-point arithmetic detected + --> $DIR/float_arithmetic.rs:19:5 + | +LL | f * 2.0; + | ^^^^^^^ + +error: floating-point arithmetic detected + --> $DIR/float_arithmetic.rs:20:5 + | +LL | f / 2.0; + | ^^^^^^^ + +error: floating-point arithmetic detected + --> $DIR/float_arithmetic.rs:21:5 + | +LL | f - 2.0 * 4.2; + | ^^^^^^^^^^^^^ + +error: floating-point arithmetic detected + --> $DIR/float_arithmetic.rs:22:5 + | +LL | -f; + | ^^ + +error: floating-point arithmetic detected + --> $DIR/float_arithmetic.rs:24:5 + | +LL | f += 1.0; + | ^^^^^^^^ + +error: floating-point arithmetic detected + --> $DIR/float_arithmetic.rs:25:5 + | +LL | f -= 1.0; + | ^^^^^^^^ + +error: floating-point arithmetic detected + --> $DIR/float_arithmetic.rs:26:5 + | +LL | f *= 2.0; + | ^^^^^^^^ + +error: floating-point arithmetic detected + --> $DIR/float_arithmetic.rs:27:5 + | +LL | f /= 2.0; + | ^^^^^^^^ + +error: floating-point arithmetic detected + --> $DIR/float_arithmetic.rs:33:5 + | +LL | 3.1_f32 + &1.2_f32; + | ^^^^^^^^^^^^^^^^^^ + +error: floating-point arithmetic detected + --> $DIR/float_arithmetic.rs:34:5 + | +LL | &3.4_f32 + 1.5_f32; + | ^^^^^^^^^^^^^^^^^^ + +error: floating-point arithmetic detected + --> $DIR/float_arithmetic.rs:35:5 + | +LL | &3.5_f32 + &1.3_f32; + | ^^^^^^^^^^^^^^^^^^^ + +error: floating-point arithmetic detected + --> $DIR/float_arithmetic.rs:40:5 + | +LL | a + f + | ^^^^^ + +error: floating-point arithmetic detected + --> $DIR/float_arithmetic.rs:44:5 + | +LL | f1 + f2 + | ^^^^^^^ + +error: floating-point arithmetic detected + --> $DIR/float_arithmetic.rs:48:5 + | +LL | f1 + f2 + | ^^^^^^^ + +error: floating-point arithmetic detected + --> $DIR/float_arithmetic.rs:52:5 + | +LL | (&f1 + &f2) + | ^^^^^^^^^^^ + +error: aborting due to 17 previous errors + diff --git a/tests/ui/arithmetic.rs b/tests/ui/integer_arithmetic.rs similarity index 71% rename from tests/ui/arithmetic.rs rename to tests/ui/integer_arithmetic.rs index 38892f6b14de..31a07e7c35b0 100644 --- a/tests/ui/arithmetic.rs +++ b/tests/ui/integer_arithmetic.rs @@ -42,25 +42,6 @@ fn main() { i &= 1; i ^= i; - let mut f = 1.0f32; - - f * 2.0; - - 1.0 + f; - f * 2.0; - f / 2.0; - f - 2.0 * 4.2; - -f; - - f += 1.0; - f -= 1.0; - f *= 2.0; - f /= 2.0; - - // no error, overflows are checked by `overflowing_literals` - -1.; - -(-1.); - // No errors for the following items because they are constant expressions enum Foo { Bar = -2, @@ -119,28 +100,3 @@ pub fn baz(x: i32, y: &i32) -> i32 { pub fn qux(x: i32, y: i32) -> i32 { (&x + &y) } - -// also warn about floating point arith with references involved - -pub fn float_arith_ref() { - 3.1_f32 + &1.2_f32; - &3.4_f32 + 1.5_f32; - &3.5_f32 + &1.3_f32; -} - -pub fn float_foo(f: &f32) -> f32 { - let a = 5.1; - a + f -} - -pub fn float_bar(f1: &f32, f2: &f32) -> f32 { - f1 + f2 -} - -pub fn float_baz(f1: f32, f2: &f32) -> f32 { - f1 + f2 -} - -pub fn float_qux(f1: f32, f2: f32) -> f32 { - (&f1 + &f2) -} diff --git a/tests/ui/integer_arithmetic.stderr b/tests/ui/integer_arithmetic.stderr new file mode 100644 index 000000000000..0b8d0b767bf8 --- /dev/null +++ b/tests/ui/integer_arithmetic.stderr @@ -0,0 +1,107 @@ +error: integer arithmetic detected + --> $DIR/integer_arithmetic.rs:15:5 + | +LL | 1 + i; + | ^^^^^ + | + = note: `-D clippy::integer-arithmetic` implied by `-D warnings` + +error: integer arithmetic detected + --> $DIR/integer_arithmetic.rs:16:5 + | +LL | i * 2; + | ^^^^^ + +error: integer arithmetic detected + --> $DIR/integer_arithmetic.rs:17:5 + | +LL | / 1 % +LL | | i / 2; // no error, this is part of the expression in the preceding line + | |_________^ + +error: integer arithmetic detected + --> $DIR/integer_arithmetic.rs:19:5 + | +LL | i - 2 + 2 - i; + | ^^^^^^^^^^^^^ + +error: integer arithmetic detected + --> $DIR/integer_arithmetic.rs:20:5 + | +LL | -i; + | ^^ + +error: integer arithmetic detected + --> $DIR/integer_arithmetic.rs:32:5 + | +LL | i += 1; + | ^^^^^^ + +error: integer arithmetic detected + --> $DIR/integer_arithmetic.rs:33:5 + | +LL | i -= 1; + | ^^^^^^ + +error: integer arithmetic detected + --> $DIR/integer_arithmetic.rs:34:5 + | +LL | i *= 2; + | ^^^^^^ + +error: integer arithmetic detected + --> $DIR/integer_arithmetic.rs:35:5 + | +LL | i /= 2; + | ^^^^^^ + +error: integer arithmetic detected + --> $DIR/integer_arithmetic.rs:36:5 + | +LL | i %= 2; + | ^^^^^^ + +error: integer arithmetic detected + --> $DIR/integer_arithmetic.rs:82:5 + | +LL | 3 + &1; + | ^^^^^^ + +error: integer arithmetic detected + --> $DIR/integer_arithmetic.rs:83:5 + | +LL | &3 + 1; + | ^^^^^^ + +error: integer arithmetic detected + --> $DIR/integer_arithmetic.rs:84:5 + | +LL | &3 + &1; + | ^^^^^^^ + +error: integer arithmetic detected + --> $DIR/integer_arithmetic.rs:89:5 + | +LL | a + x + | ^^^^^ + +error: integer arithmetic detected + --> $DIR/integer_arithmetic.rs:93:5 + | +LL | x + y + | ^^^^^ + +error: integer arithmetic detected + --> $DIR/integer_arithmetic.rs:97:5 + | +LL | x + y + | ^^^^^ + +error: integer arithmetic detected + --> $DIR/integer_arithmetic.rs:101:5 + | +LL | (&x + &y) + | ^^^^^^^^^ + +error: aborting due to 17 previous errors + From 0812a0af4c6acc063320c9617dd47c85860dcbf5 Mon Sep 17 00:00:00 2001 From: Rabi Guha Date: Mon, 16 Mar 2020 17:14:24 +0530 Subject: [PATCH 234/243] Improvement: Don't show function body in needless_lifetimes Changes the span on which the lint is reported to point to only the function return type instead of the entire function body. Fixes #5284 --- clippy_lints/src/lifetimes.rs | 2 +- tests/ui/issue_4266.stderr | 8 ++- tests/ui/needless_lifetimes.stderr | 84 ++++++++++-------------------- 3 files changed, 32 insertions(+), 62 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 85d3e9029dff..b510b293617a 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -169,7 +169,7 @@ fn check_fn_inner<'a, 'tcx>( span_lint( cx, NEEDLESS_LIFETIMES, - span, + span.with_hi(decl.output.span().hi()), "explicit lifetimes given in parameter types where they could be elided \ (or replaced with `'_` if needed by type declaration)", ); diff --git a/tests/ui/issue_4266.stderr b/tests/ui/issue_4266.stderr index 2ebe85bd6b0e..0426508e622f 100644 --- a/tests/ui/issue_4266.stderr +++ b/tests/ui/issue_4266.stderr @@ -2,17 +2,15 @@ error: explicit lifetimes given in parameter types where they could be elided (o --> $DIR/issue_4266.rs:4:1 | LL | async fn sink1<'a>(_: &'a str) {} // lint - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::needless-lifetimes` implied by `-D warnings` error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/issue_4266.rs:8:1 | -LL | / async fn one_to_one<'a>(s: &'a str) -> &'a str { -LL | | s -LL | | } - | |_^ +LL | async fn one_to_one<'a>(s: &'a str) -> &'a str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/needless_lifetimes.stderr b/tests/ui/needless_lifetimes.stderr index ad55fc5f750d..d3a360ed8b57 100644 --- a/tests/ui/needless_lifetimes.stderr +++ b/tests/ui/needless_lifetimes.stderr @@ -2,7 +2,7 @@ error: explicit lifetimes given in parameter types where they could be elided (o --> $DIR/needless_lifetimes.rs:4:1 | LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::needless-lifetimes` implied by `-D warnings` @@ -10,125 +10,97 @@ error: explicit lifetimes given in parameter types where they could be elided (o --> $DIR/needless_lifetimes.rs:6:1 | LL | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/needless_lifetimes.rs:16:1 | -LL | / fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { -LL | | x -LL | | } - | |_^ +LL | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/needless_lifetimes.rs:45:1 | -LL | / fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { -LL | | Ok(x) -LL | | } - | |_^ +LL | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/needless_lifetimes.rs:50:1 | -LL | / fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> -LL | | where -LL | | T: Copy, -LL | | { -LL | | Ok(x) -LL | | } - | |_^ +LL | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/needless_lifetimes.rs:62:1 | LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/needless_lifetimes.rs:86:1 | -LL | / fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> -LL | | where -LL | | for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>, -LL | | { -LL | | unreachable!() -LL | | } - | |_^ +LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/needless_lifetimes.rs:120:5 | -LL | / fn self_and_out<'s>(&'s self) -> &'s u8 { -LL | | &self.x -LL | | } - | |_____^ +LL | fn self_and_out<'s>(&'s self) -> &'s u8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/needless_lifetimes.rs:129:5 | LL | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/needless_lifetimes.rs:148:1 | -LL | / fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { -LL | | unimplemented!() -LL | | } - | |_^ +LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/needless_lifetimes.rs:178:1 | -LL | / fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str { -LL | | unimplemented!() -LL | | } - | |_^ +LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/needless_lifetimes.rs:184:1 | -LL | / fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { -LL | | unimplemented!() -LL | | } - | |_^ +LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/needless_lifetimes.rs:203:1 | -LL | / fn named_input_elided_output<'a>(_arg: &'a str) -> &str { -LL | | unimplemented!() -LL | | } - | |_^ +LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/needless_lifetimes.rs:211:1 | -LL | / fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { -LL | | unimplemented!() -LL | | } - | |_^ +LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/needless_lifetimes.rs:247:1 | -LL | / fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { -LL | | unimplemented!() -LL | | } - | |_^ +LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/needless_lifetimes.rs:254:9 | LL | fn needless_lt<'a>(x: &'a u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) --> $DIR/needless_lifetimes.rs:258:9 | LL | fn needless_lt<'a>(_x: &'a u8) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 17 previous errors From b9d6bf3bfb6e0a0be793a9352d5568f1cd0d8470 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 18 Mar 2020 23:45:02 +0100 Subject: [PATCH 235/243] rustup https://github.com/rust-lang/rust/pull/69920/ --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/missing_inline.rs | 2 +- clippy_lints/src/trivially_copy_pass_by_ref.rs | 2 +- clippy_lints/src/utils/attrs.rs | 2 +- clippy_lints/src/utils/author.rs | 2 +- clippy_lints/src/utils/inspector.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index fb79ad271e0a..1c81d78a2b95 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -56,9 +56,9 @@ extern crate rustc_trait_selection; #[allow(unused_extern_crates)] extern crate rustc_typeck; -use rustc::session::Session; use rustc_data_structures::fx::FxHashSet; use rustc_lint::LintId; +use rustc_session::Session; /// Macro used to declare a Clippy lint. /// diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index 0f871d29c2f3..22b56c28b6bc 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -69,7 +69,7 @@ fn check_missing_inline_attrs(cx: &LateContext<'_, '_>, attrs: &[ast::Attribute] } fn is_executable(cx: &LateContext<'_, '_>) -> bool { - use rustc::session::config::CrateType; + use rustc_session::config::CrateType; cx.tcx.sess.crate_types.get().iter().any(|t: &CrateType| match t { CrateType::Executable => true, diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 7e9a94f14fef..194e11ac9bdf 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -3,13 +3,13 @@ use std::cmp; use crate::utils::{is_copy, is_self_ty, snippet, span_lint_and_sugg}; use if_chain::if_chain; use matches::matches; -use rustc::session::config::Config as SessionConfig; use rustc::ty; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl, HirId, ItemKind, MutTy, Mutability, Node}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::config::Config as SessionConfig; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::Span; use rustc_target::abi::LayoutOf; diff --git a/clippy_lints/src/utils/attrs.rs b/clippy_lints/src/utils/attrs.rs index 3721350959b9..e27e1b7f2e6c 100644 --- a/clippy_lints/src/utils/attrs.rs +++ b/clippy_lints/src/utils/attrs.rs @@ -1,6 +1,6 @@ -use rustc::session::Session; use rustc_ast::ast; use rustc_errors::Applicability; +use rustc_session::Session; use std::str::FromStr; /// Deprecation status of attributes known by Clippy. diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index e95c45852ac2..4fcaf4264d77 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -3,7 +3,6 @@ use crate::utils::{get_attr, higher}; use rustc::hir::map::Map; -use rustc::session::Session; use rustc_ast::ast::{Attribute, LitFloatType, LitKind}; use rustc_ast::walk_list; use rustc_data_structures::fx::FxHashMap; @@ -11,6 +10,7 @@ use rustc_hir as hir; use rustc_hir::intravisit::{NestedVisitorMap, Visitor}; use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, Pat, PatKind, QPath, Stmt, StmtKind, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_session::Session; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index d79f6d525fcf..c6a47f05e248 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -1,11 +1,11 @@ //! checks for attributes use crate::utils::get_attr; -use rustc::session::Session; use rustc_ast::ast::Attribute; use rustc_hir as hir; use rustc_hir::print; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_session::Session; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { From 21aeb21b8afa18c076180b8ae5e221e1d020911d Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 19 Mar 2020 14:33:10 +0100 Subject: [PATCH 236/243] Rustup to rust-lang/rust#66131 --- clippy_lints/src/functions.rs | 4 ++-- clippy_lints/src/inherent_impl.rs | 4 ++-- clippy_lints/src/loops.rs | 2 +- clippy_lints/src/missing_doc.rs | 2 +- clippy_lints/src/new_without_default.rs | 4 ++-- clippy_lints/src/swap.rs | 2 +- clippy_lints/src/utils/mod.rs | 4 ++-- clippy_lints/src/utils/usage.rs | 4 ++-- clippy_lints/src/wildcard_imports.rs | 2 +- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 01ced205af48..697486c1af09 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -486,7 +486,7 @@ fn is_mutable_pat(cx: &LateContext<'_, '_>, pat: &hir::Pat<'_>, tys: &mut FxHash if let hir::PatKind::Wild = pat.kind { return false; // ignore `_` patterns } - let def_id = pat.hir_id.owner_def_id(); + let def_id = pat.hir_id.owner.to_def_id(); if cx.tcx.has_typeck_tables(def_id) { is_mutable_ty(cx, &cx.tcx.typeck_tables_of(def_id).pat_ty(pat), pat.span, tys) } else { @@ -601,7 +601,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> { Call(_, args) | MethodCall(_, _, args) => { let mut tys = FxHashSet::default(); for arg in args { - let def_id = arg.hir_id.owner_def_id(); + let def_id = arg.hir_id.owner.to_def_id(); if self.cx.tcx.has_typeck_tables(def_id) && is_mutable_ty( self.cx, diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index 355e75d0d559..cd034f916cef 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -59,7 +59,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MultipleInherentImpl { // but filter out implementations that have generic params (type or lifetime) // or are derived from a macro if !in_macro(item.span) && generics.params.is_empty() { - self.impls.insert(item.hir_id.owner_def_id(), item.span); + self.impls.insert(item.hir_id.owner.to_def_id(), item.span); } } } @@ -69,7 +69,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MultipleInherentImpl { // Retrieve all inherent implementations from the crate, grouped by type for impls in cx .tcx - .crate_inherent_impls(item.hir_id.owner_def_id().krate) + .crate_inherent_impls(item.hir_id.owner.to_def_id().krate) .inherent_impls .values() { diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 211d9034ffb7..475e60736e07 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1679,7 +1679,7 @@ fn check_for_mutation( span_low: None, span_high: None, }; - let def_id = def_id::DefId::local(body.hir_id.owner); + let def_id = body.hir_id.owner.to_def_id(); cx.tcx.infer_ctxt().enter(|infcx| { ExprUseVisitor::new(&mut delegate, &infcx, def_id, cx.param_env, cx.tables).walk_expr(body); }); diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 96750cb3b466..e03f9e36095b 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -135,7 +135,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { hir::ItemKind::Fn(..) => { // ignore main() if it.ident.name == sym!(main) { - let def_id = cx.tcx.hir().local_def_id(it.hir_id); + let def_id = it.hir_id.owner; let def_key = cx.tcx.hir().def_key(def_id); if def_key.parent == Some(hir::def_id::CRATE_DEF_INDEX) { return; diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index adc93909677d..f69b145fa39f 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -149,9 +149,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { if_chain! { if let Some(ref impling_types) = self.impling_types; if let Some(self_def) = cx.tcx.type_of(self_did).ty_adt_def(); - if self_def.did.is_local(); + if let Some(self_def_id) = self_def.did.as_local(); then { - let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_def.did.to_local()); + let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_def_id); if impling_types.contains(&self_id) { return; } diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 05428f1a31fb..d532efbec749 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -99,7 +99,7 @@ fn check_manual_swap(cx: &LateContext<'_, '_>, block: &Block<'_>) { then { if let ExprKind::Field(ref lhs1, _) = lhs1.kind { if let ExprKind::Field(ref lhs2, _) = lhs2.kind { - if lhs1.hir_id.owner_def_id() == lhs2.hir_id.owner_def_id() { + if lhs1.hir_id.owner == lhs2.hir_id.owner { return; } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 280e8e2f32e6..c1c5bcc1dd1b 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -297,8 +297,8 @@ pub fn qpath_res(cx: &LateContext<'_, '_>, qpath: &hir::QPath<'_>, id: hir::HirI match qpath { hir::QPath::Resolved(_, path) => path.res, hir::QPath::TypeRelative(..) => { - if cx.tcx.has_typeck_tables(id.owner_def_id()) { - cx.tcx.typeck_tables_of(id.owner_def_id()).qpath_res(qpath, id) + if cx.tcx.has_typeck_tables(id.owner.to_def_id()) { + cx.tcx.typeck_tables_of(id.owner.to_def_id()).qpath_res(qpath, id) } else { Res::Err } diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs index 7cde18fdb3b4..a08251c1a4eb 100644 --- a/clippy_lints/src/utils/usage.rs +++ b/clippy_lints/src/utils/usage.rs @@ -5,7 +5,7 @@ use rustc_ast::ast; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; -use rustc_hir::{def_id, Expr, HirId, Path}; +use rustc_hir::{Expr, HirId, Path}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_span::symbol::Ident; @@ -17,7 +17,7 @@ pub fn mutated_variables<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &'a LateContext<'a, used_mutably: FxHashSet::default(), skip: false, }; - let def_id = def_id::DefId::local(expr.hir_id.owner); + let def_id = expr.hir_id.owner.to_def_id(); cx.tcx.infer_ctxt().enter(|infcx| { ExprUseVisitor::new(&mut delegate, &infcx, def_id, cx.param_env, cx.tables).walk_expr(expr); }); diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 6f8cec7c0567..348d13ef41f1 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -85,7 +85,7 @@ impl LateLintPass<'_, '_> for WildcardImports { if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; // don't lint prelude glob imports if !use_path.segments.iter().last().map_or(false, |ps| ps.ident.as_str() == "prelude"); - let used_imports = cx.tcx.names_imported_by_glob_use(item.hir_id.owner_def_id()); + let used_imports = cx.tcx.names_imported_by_glob_use(item.hir_id.owner.to_def_id()); if !used_imports.is_empty(); // Already handled by `unused_imports` then { let mut applicability = Applicability::MachineApplicable; From e4fc9316cd25fca678b6a37ec53a21fb6bdc8dbb Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 19 Mar 2020 13:58:08 +0100 Subject: [PATCH 237/243] Get integration test binary from deps dir cc rust-lang/cargo#7965 --- .github/workflows/clippy_bors.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index a4f7b64cb6a7..6675a1029bbc 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -208,8 +208,9 @@ jobs: - name: Extract Binaries run: | DIR=$CARGO_TARGET_DIR/debug + rm $DIR/deps/integration-*.d + mv $DIR/deps/integration-* $DIR/integration find $DIR ! -executable -o -type d ! -path $DIR | xargs rm -rf - mv $DIR/integration-* $DIR/integration rm -rf $CARGO_TARGET_DIR/release - name: Upload Binaries From badfbbbbde9b95c3c87c75d3c15fee1fd500befd Mon Sep 17 00:00:00 2001 From: ThibsG Date: Sat, 21 Mar 2020 20:26:55 +0100 Subject: [PATCH 238/243] Fix single binding in closure --- clippy_lints/src/matches.rs | 26 ++++++++++++++++++++------ tests/ui/match_single_binding.fixed | 10 ++++++++++ tests/ui/match_single_binding.rs | 9 +++++++++ tests/ui/match_single_binding.stderr | 19 ++++++++++++++++++- 4 files changed, 57 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index b0aae5e30e6e..40880f78270c 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -3,9 +3,10 @@ use crate::utils::paths; use crate::utils::sugg::Sugg; use crate::utils::usage::is_unused; use crate::utils::{ - expr_block, get_arg_name, in_macro, indent_of, is_allowed, is_expn_of, is_refutable, is_wild, match_qpath, - match_type, match_var, multispan_sugg, remove_blocks, snippet, snippet_block, snippet_with_applicability, - span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then, walk_ptrs_ty, + expr_block, get_arg_name, get_parent_expr, in_macro, indent_of, is_allowed, is_expn_of, is_refutable, is_wild, + match_qpath, match_type, match_var, multispan_sugg, remove_blocks, snippet, snippet_block, + snippet_with_applicability, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then, + walk_ptrs_ty, }; use if_chain::if_chain; use rustc::lint::in_external_macro; @@ -928,14 +929,27 @@ fn check_match_single_binding<'a>(cx: &LateContext<'_, 'a>, ex: &Expr<'a>, arms: ), ) } else { + // If we are in closure, we need curly braces around suggestion + let mut indent = " ".repeat(indent_of(cx, ex.span).unwrap_or(0)); + let (mut cbrace_start, mut cbrace_end) = ("".to_string(), "".to_string()); + if let Some(parent_expr) = get_parent_expr(cx, expr) { + if let ExprKind::Closure(..) = parent_expr.kind { + cbrace_end = format!("\n{}}}", indent); + // Fix body indent due to the closure + indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0)); + cbrace_start = format!("{{\n{}", indent); + } + }; ( expr.span, format!( - "let {} = {};\n{}{}", + "{}let {} = {};\n{}{}{}", + cbrace_start, snippet_with_applicability(cx, bind_names, "..", &mut applicability), snippet_with_applicability(cx, matched_vars, "..", &mut applicability), - " ".repeat(indent_of(cx, expr.span).unwrap_or(0)), - snippet_body + indent, + snippet_body, + cbrace_end ), ) }; diff --git a/tests/ui/match_single_binding.fixed b/tests/ui/match_single_binding.fixed index bc2346a8dbf0..90f00aa78712 100644 --- a/tests/ui/match_single_binding.fixed +++ b/tests/ui/match_single_binding.fixed @@ -67,4 +67,14 @@ fn main() { // Lint let Point { x, y } = coords(); let product = x * y; + // Lint + let v = vec![Some(1), Some(2), Some(3), Some(4)]; + #[allow(clippy::let_and_return)] + let _ = v + .iter() + .map(|i| { + let unwrapped = i.unwrap(); + unwrapped + }) + .collect::>(); } diff --git a/tests/ui/match_single_binding.rs b/tests/ui/match_single_binding.rs index 0517b3bbfbf9..4a4b290036c7 100644 --- a/tests/ui/match_single_binding.rs +++ b/tests/ui/match_single_binding.rs @@ -80,4 +80,13 @@ fn main() { let product = match coords() { Point { x, y } => x * y, }; + // Lint + let v = vec![Some(1), Some(2), Some(3), Some(4)]; + #[allow(clippy::let_and_return)] + let _ = v + .iter() + .map(|i| match i.unwrap() { + unwrapped => unwrapped, + }) + .collect::>(); } diff --git a/tests/ui/match_single_binding.stderr b/tests/ui/match_single_binding.stderr index 05ba9e5f7f3c..cf741a989c2d 100644 --- a/tests/ui/match_single_binding.stderr +++ b/tests/ui/match_single_binding.stderr @@ -150,5 +150,22 @@ LL | let Point { x, y } = coords(); LL | let product = x * y; | -error: aborting due to 10 previous errors +error: this match could be written as a `let` statement + --> $DIR/match_single_binding.rs:88:18 + | +LL | .map(|i| match i.unwrap() { + | __________________^ +LL | | unwrapped => unwrapped, +LL | | }) + | |_________^ + | +help: consider using `let` statement + | +LL | .map(|i| { +LL | let unwrapped = i.unwrap(); +LL | unwrapped +LL | }) + | + +error: aborting due to 11 previous errors From a1dc609f2182be97caf23fc22ab02d962033c8e9 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sun, 22 Mar 2020 18:15:06 +0100 Subject: [PATCH 239/243] Fix documentation generation for configurable lints --- util/lintlib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/lintlib.py b/util/lintlib.py index a260e00cde46..16cc6ccfdae3 100644 --- a/util/lintlib.py +++ b/util/lintlib.py @@ -14,7 +14,7 @@ group_re = re.compile(r'''\s*([a-z_][a-z_0-9]+)''') conf_re = re.compile(r'''define_Conf! {\n([^}]*)\n}''', re.MULTILINE) confvar_re = re.compile( - r'''/// Lint: (\w+). (.*).*\n\s*\([^,]+,\s+"([^"]+)",\s+([^=\)]+)=>\s+(.*)\),''', re.MULTILINE) + r'''/// Lint: (\w+)\. (.*)\n\s*\([^,]+,\s+"([^"]+)":\s+([^,]+),\s+([^\.\)]+).*\),''', re.MULTILINE) comment_re = re.compile(r'''\s*/// ?(.*)''') lint_levels = { @@ -93,7 +93,7 @@ def parse_configs(path): match = re.search(conf_re, contents) confvars = re.findall(confvar_re, match.group(1)) - for (lint, doc, name, default, ty) in confvars: + for (lint, doc, name, ty, default) in confvars: configs[lint.lower()] = Config(name.replace("_", "-"), ty, doc, default) return configs From 0f319513d25de94a5bf3edfab9fbff14e296eafb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 23 Mar 2020 15:21:46 +0100 Subject: [PATCH 240/243] rustup https://github.com/rust-lang/rust/pull/69968/ --- clippy_lints/src/doc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 9b028cd0f76b..63b8d519c9d0 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -234,8 +234,8 @@ fn lint_for_missing_headers<'a, 'tcx>( if implements_trait(cx, ret_ty, future, &[]); if let ty::Opaque(_, subs) = ret_ty.kind; if let Some(gen) = subs.types().next(); - if let ty::Generator(def_id, subs, _) = gen.kind; - if match_type(cx, subs.as_generator().return_ty(def_id, cx.tcx), &paths::RESULT); + if let ty::Generator(_, subs, _) = gen.kind; + if match_type(cx, subs.as_generator().return_ty(), &paths::RESULT); then { span_lint( cx, From e1fc6499eeaf8c8c5df8a5aff394bd962d07b53a Mon Sep 17 00:00:00 2001 From: mgr-inz-rafal Date: Mon, 3 Feb 2020 21:19:50 +0100 Subject: [PATCH 241/243] Initial lint infrastructure --- clippy_lints/src/needless_bool.rs | 11 ++++++++++- tests/ui/bool_comparison.fixed | 7 +++++++ tests/ui/bool_comparison.rs | 7 +++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 19c22d2b791c..e58763ef3132 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -199,9 +199,18 @@ fn check_comparison<'a, 'tcx>( ) { use self::Expression::{Bool, Other}; - if let ExprKind::Binary(_, ref left_side, ref right_side) = e.kind { + if let ExprKind::Binary(op, ref left_side, ref right_side) = e.kind { let (l_ty, r_ty) = (cx.tables.expr_ty(left_side), cx.tables.expr_ty(right_side)); if l_ty.is_bool() && r_ty.is_bool() { + if let BinOpKind::Eq = op.node { + if let ExprKind::Unary(unop, exx) = right_side.kind + { + if let UnOp::UnNot = unop { + // TODO: Lint here + } + } + } + let mut applicability = Applicability::MachineApplicable; match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { (Bool(true), Other) => left_true.map_or((), |(h, m)| { diff --git a/tests/ui/bool_comparison.fixed b/tests/ui/bool_comparison.fixed index 0bd73ec2c104..ccbbf950e830 100644 --- a/tests/ui/bool_comparison.fixed +++ b/tests/ui/bool_comparison.fixed @@ -111,3 +111,10 @@ fn issue3703() { if Foo < false {} if false < Foo {} } + +fn issue4983() { + let a = true; + let b = false; + + //if a == !b {}; +} diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index 74f504edfd06..f2e62d028f7a 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -111,3 +111,10 @@ fn issue3703() { if Foo < false {} if false < Foo {} } + +fn issue4983() { + let a = true; + let b = false; + + if a == !b {}; +} From 154b2d4892fb719f10784244f252a0380be1d798 Mon Sep 17 00:00:00 2001 From: mgr-inz-rafal Date: Tue, 4 Feb 2020 21:01:59 +0100 Subject: [PATCH 242/243] Detect offending comparison --- clippy_lints/src/needless_bool.rs | 31 +++++++++++++++++++++++-------- tests/ui/bool_comparison.rs | 3 +++ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index e58763ef3132..3df049f952b2 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -2,9 +2,10 @@ //! //! This lint is **warn** by default +use if_chain::if_chain; use crate::utils::sugg::Sugg; -use crate::utils::{higher, parent_node_is_if_expr, span_lint, span_lint_and_sugg}; use rustc_ast::ast::LitKind; +use crate::utils::{higher, parent_node_is_if_expr, span_lint, span_lint_and_help, span_lint_and_sugg}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -188,6 +189,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { } } +fn is_unary_not<'tcx>(e: &'tcx Expr<'_>) -> bool { + if_chain! { + if let ExprKind::Unary(unop, _) = e.kind; + if let UnOp::UnNot = unop; + then { + return true; + } + }; + false + } + +fn one_side_is_unary_not<'tcx>(left_side: &'tcx Expr<'_>, right_side: &'tcx Expr<'_>) -> bool { + is_unary_not(left_side) ^ is_unary_not(right_side) +} + fn check_comparison<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>, @@ -202,14 +218,13 @@ fn check_comparison<'a, 'tcx>( if let ExprKind::Binary(op, ref left_side, ref right_side) = e.kind { let (l_ty, r_ty) = (cx.tables.expr_ty(left_side), cx.tables.expr_ty(right_side)); if l_ty.is_bool() && r_ty.is_bool() { - if let BinOpKind::Eq = op.node { - if let ExprKind::Unary(unop, exx) = right_side.kind - { - if let UnOp::UnNot = unop { - // TODO: Lint here - } + if_chain! { + if let BinOpKind::Eq = op.node; + if one_side_is_unary_not(&left_side, &right_side); + then { + span_lint_and_help(cx, BOOL_COMPARISON, e.span, "help1", "help2"); } - } + }; let mut applicability = Applicability::MachineApplicable; match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index f2e62d028f7a..c13575eae717 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -117,4 +117,7 @@ fn issue4983() { let b = false; if a == !b {}; + if !a == b {}; + if a == b {}; + if !a == !b {}; } From 6160e87f6739100280f3949d707c2c109fbac092 Mon Sep 17 00:00:00 2001 From: mgr-inz-rafal Date: Thu, 6 Feb 2020 20:36:54 +0100 Subject: [PATCH 243/243] Add issue4983() to test --- clippy_lints/src/needless_bool.rs | 6 +++--- tests/ui/bool_comparison.stderr | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 3df049f952b2..f2c58f582722 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -2,10 +2,10 @@ //! //! This lint is **warn** by default -use if_chain::if_chain; use crate::utils::sugg::Sugg; use rustc_ast::ast::LitKind; use crate::utils::{higher, parent_node_is_if_expr, span_lint, span_lint_and_help, span_lint_and_sugg}; +use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -198,7 +198,7 @@ fn is_unary_not<'tcx>(e: &'tcx Expr<'_>) -> bool { } }; false - } +} fn one_side_is_unary_not<'tcx>(left_side: &'tcx Expr<'_>, right_side: &'tcx Expr<'_>) -> bool { is_unary_not(left_side) ^ is_unary_not(right_side) @@ -222,7 +222,7 @@ fn check_comparison<'a, 'tcx>( if let BinOpKind::Eq = op.node; if one_side_is_unary_not(&left_side, &right_side); then { - span_lint_and_help(cx, BOOL_COMPARISON, e.span, "help1", "help2"); + span_lint_and_help(cx, BOOL_COMPARISON, e.span, "Here comes", "the suggestion"); } }; diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index 2aa070a00f30..cec7b196a23f 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -84,5 +84,21 @@ error: order comparisons between booleans can be simplified LL | if x > y { | ^^^^^ help: try simplifying it as shown: `x & !y` -error: aborting due to 14 previous errors +error: Here comes + --> $DIR/bool_comparison.rs:119:8 + | +LL | if a == !b {}; + | ^^^^^^^ + | + = help: the suggestion + +error: Here comes + --> $DIR/bool_comparison.rs:120:8 + | +LL | if !a == b {}; + | ^^^^^^^ + | + = help: the suggestion + +error: aborting due to 16 previous errors