diff --git a/CHANGELOG.md b/CHANGELOG.md index 2278a8dc1..380cd4519 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -965,7 +965,7 @@ Released 2021-09-09 [#7407](https://github.com/rust-lang/rust-clippy/pull/7407) * [`redundant_allocation`]: Now additionally supports the `Arc<>` type [#7308](https://github.com/rust-lang/rust-clippy/pull/7308) -* [`blacklisted_name`]: Now allows blacklisted names in test code +* [`disallowed_names`]: Now allows disallowed names in test code [#7379](https://github.com/rust-lang/rust-clippy/pull/7379) * [`redundant_closure`]: Suggests `&mut` for `FnMut` [#7437](https://github.com/rust-lang/rust-clippy/pull/7437) @@ -2066,7 +2066,7 @@ Released 2020-08-27 [#5692](https://github.com/rust-lang/rust-clippy/pull/5692) * [`if_same_then_else`]: Don't assume multiplication is always commutative [#5702](https://github.com/rust-lang/rust-clippy/pull/5702) -* [`blacklisted_name`]: Remove `bar` from the default configuration +* [`disallowed_names`]: Remove `bar` from the default configuration [#5712](https://github.com/rust-lang/rust-clippy/pull/5712) * [`redundant_pattern_matching`]: Avoid suggesting non-`const fn` calls in const contexts [#5724](https://github.com/rust-lang/rust-clippy/pull/5724) @@ -3522,6 +3522,7 @@ Released 2018-09-13 [`derive_partial_eq_without_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq [`disallowed_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_method [`disallowed_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods +[`disallowed_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names [`disallowed_script_idents`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents [`disallowed_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type [`disallowed_types`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types @@ -3685,6 +3686,7 @@ Released 2018-09-13 [`manual_find`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find [`manual_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find_map [`manual_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_flatten +[`manual_instant_elapsed`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_instant_elapsed [`manual_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_map [`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy [`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive @@ -3816,11 +3818,13 @@ Released 2018-09-13 [`or_then_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#or_then_unwrap [`out_of_bounds_indexing`]: https://rust-lang.github.io/rust-clippy/master/index.html#out_of_bounds_indexing [`overflow_check_conditional`]: https://rust-lang.github.io/rust-clippy/master/index.html#overflow_check_conditional +[`overly_complex_bool_expr`]: https://rust-lang.github.io/rust-clippy/master/index.html#overly_complex_bool_expr [`panic`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic [`panic_in_result_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic_in_result_fn [`panic_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic_params [`panicking_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#panicking_unwrap [`partialeq_ne_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_ne_impl +[`partialeq_to_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_to_none [`path_buf_push_overwrite`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_buf_push_overwrite [`pattern_type_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#pattern_type_mismatch [`possible_missing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_comma diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6e15133d2..28b4cfd5f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,10 +30,10 @@ All contributors are expected to follow the [Rust Code of Conduct]. ## The Clippy book If you're new to Clippy and don't know where to start the [Clippy book] includes -a developer guide and is a good place to start your journey. +a [developer guide] and is a good place to start your journey. - -[Clippy book]: book/src +[Clippy book]: https://doc.rust-lang.org/nightly/clippy/index.html +[developer guide]: https://doc.rust-lang.org/nightly/clippy/development/index.html ## High level approach diff --git a/Cargo.toml b/Cargo.toml index 1c875c3ad..b7e136ce9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.64" +version = "0.1.65" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/README.md b/README.md index 2c3defeaa..1193771ff 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,7 @@ value` mapping e.g. ```toml avoid-breaking-exported-api = false -blacklisted-names = ["toto", "tata", "titi"] +disallowed-names = ["toto", "tata", "titi"] cognitive-complexity-threshold = 30 ``` diff --git a/book/src/configuration.md b/book/src/configuration.md index 6e295ac31..77f1d2e87 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -7,7 +7,7 @@ basic `variable = value` mapping eg. ```toml avoid-breaking-exported-api = false -blacklisted-names = ["toto", "tata", "titi"] +disallowed-names = ["toto", "tata", "titi"] cognitive-complexity-threshold = 30 ``` diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index 03d2ef3d1..10a8f31f4 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -438,7 +438,7 @@ fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str> let mut lint_context = None; let mut iter = rustc_lexer::tokenize(&file_contents).map(|t| { - let range = offset..offset + t.len; + let range = offset..offset + t.len as usize; offset = range.end; LintDeclSearchResult { diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs index aed38bc28..05e79a241 100644 --- a/clippy_dev/src/update_lints.rs +++ b/clippy_dev/src/update_lints.rs @@ -836,7 +836,7 @@ pub(crate) struct LintDeclSearchResult<'a> { fn parse_contents(contents: &str, module: &str, lints: &mut Vec) { let mut offset = 0usize; let mut iter = tokenize(contents).map(|t| { - let range = offset..offset + t.len; + let range = offset..offset + t.len as usize; offset = range.end; LintDeclSearchResult { @@ -899,7 +899,7 @@ fn parse_contents(contents: &str, module: &str, lints: &mut Vec) { fn parse_deprecated_contents(contents: &str, lints: &mut Vec) { let mut offset = 0usize; let mut iter = tokenize(contents).map(|t| { - let range = offset..offset + t.len; + let range = offset..offset + t.len as usize; offset = range.end; LintDeclSearchResult { @@ -946,7 +946,7 @@ fn parse_renamed_contents(contents: &str, lints: &mut Vec) { for line in contents.lines() { let mut offset = 0usize; let mut iter = tokenize(line).map(|t| { - let range = offset..offset + t.len; + let range = offset..offset + t.len as usize; offset = range.end; LintDeclSearchResult { diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 79a56dc40..738562ef8 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.64" +version = "0.1.65" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/clippy_lints/src/assertions_on_result_states.rs b/clippy_lints/src/assertions_on_result_states.rs index 4caab6230..6a6554f96 100644 --- a/clippy_lints/src/assertions_on_result_states.rs +++ b/clippy_lints/src/assertions_on_result_states.rs @@ -53,13 +53,14 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates { if result_type_with_refs != result_type { return; } else if let Res::Local(binding_id) = path_res(cx, recv) - && local_used_after_expr(cx, binding_id, recv) { + && local_used_after_expr(cx, binding_id, recv) + { return; } } let mut app = Applicability::MachineApplicable; match method_segment.ident.as_str() { - "is_ok" if has_debug_impl(cx, substs.type_at(1)) => { + "is_ok" if type_suitable_to_unwrap(cx, substs.type_at(1)) => { span_lint_and_sugg( cx, ASSERTIONS_ON_RESULT_STATES, @@ -73,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates { app, ); } - "is_err" if has_debug_impl(cx, substs.type_at(0)) => { + "is_err" if type_suitable_to_unwrap(cx, substs.type_at(0)) => { span_lint_and_sugg( cx, ASSERTIONS_ON_RESULT_STATES, @@ -99,3 +100,7 @@ fn has_debug_impl<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { .get_diagnostic_item(sym::Debug) .map_or(false, |debug| implements_trait(cx, ty, debug, &[])) } + +fn type_suitable_to_unwrap<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { + has_debug_impl(cx, ty) && !ty.is_unit() && !ty.is_never() +} diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 526ee2f89..6eb78d21e 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -64,7 +64,7 @@ declare_clippy_lint! { /// if a {} /// ``` #[clippy::version = "pre 1.29.0"] - pub LOGIC_BUG, + pub OVERLY_COMPLEX_BOOL_EXPR, correctness, "boolean expressions that contain terminals which can be eliminated" } @@ -72,7 +72,7 @@ declare_clippy_lint! { // For each pairs, both orders are considered. const METHODS_WITH_NEGATION: [(&str, &str); 2] = [("is_some", "is_none"), ("is_err", "is_ok")]; -declare_lint_pass!(NonminimalBool => [NONMINIMAL_BOOL, LOGIC_BUG]); +declare_lint_pass!(NonminimalBool => [NONMINIMAL_BOOL, OVERLY_COMPLEX_BOOL_EXPR]); impl<'tcx> LateLintPass<'tcx> for NonminimalBool { fn check_fn( @@ -396,7 +396,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { if stats.terminals[i] != 0 && simplified_stats.terminals[i] == 0 { span_lint_hir_and_then( self.cx, - LOGIC_BUG, + OVERLY_COMPLEX_BOOL_EXPR, e.hir_id, e.span, "this boolean expression contains a logic bug", diff --git a/clippy_lints/src/casts/cast_abs_to_unsigned.rs b/clippy_lints/src/casts/cast_abs_to_unsigned.rs index 64ea326b7..6426e8c25 100644 --- a/clippy_lints/src/casts/cast_abs_to_unsigned.rs +++ b/clippy_lints/src/casts/cast_abs_to_unsigned.rs @@ -37,7 +37,7 @@ pub(super) fn check( span, &format!("casting the result of `{cast_from}::abs()` to {cast_to}"), "replace with", - format!("{}.unsigned_abs()", Sugg::hir(cx, &args[0], "..")), + format!("{}.unsigned_abs()", Sugg::hir(cx, &args[0], "..").maybe_par()), Applicability::MachineApplicable, ); } diff --git a/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs index 17fc81951..37b2fdcff 100644 --- a/clippy_lints/src/checked_conversions.rs +++ b/clippy_lints/src/checked_conversions.rs @@ -270,10 +270,7 @@ fn get_types_from_cast<'a>( let limit_from: Option<(&Expr<'_>, &str)> = call_from_cast.or_else(|| { if_chain! { // `from_type::from, to_type::max_value()` - if let ExprKind::Call(from_func, args) = &expr.kind; - // `to_type::max_value()` - if args.len() == 1; - if let limit = &args[0]; + if let ExprKind::Call(from_func, [limit]) = &expr.kind; // `from_type::from` if let ExprKind::Path(ref path) = &from_func.kind; if let Some(from_sym) = get_implementing_type(path, INTS, "from"); diff --git a/clippy_lints/src/create_dir.rs b/clippy_lints/src/create_dir.rs index 18d34370a..878248a6b 100644 --- a/clippy_lints/src/create_dir.rs +++ b/clippy_lints/src/create_dir.rs @@ -34,7 +34,7 @@ declare_lint_pass!(CreateDir => [CREATE_DIR]); impl LateLintPass<'_> for CreateDir { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { - if let ExprKind::Call(func, args) = expr.kind; + if let ExprKind::Call(func, [arg, ..]) = expr.kind; if let ExprKind::Path(ref path) = func.kind; if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::STD_FS_CREATE_DIR); @@ -45,7 +45,7 @@ impl LateLintPass<'_> for CreateDir { expr.span, "calling `std::fs::create_dir` where there may be a better way", "consider calling `std::fs::create_dir_all` instead", - format!("create_dir_all({})", snippet(cx, args[0].span, "..")), + format!("create_dir_all({})", snippet(cx, arg.span, "..")), Applicability::MaybeIncorrect, ) } diff --git a/clippy_lints/src/default.rs b/clippy_lints/src/default.rs index d99a1aa29..74f7df611 100644 --- a/clippy_lints/src/default.rs +++ b/clippy_lints/src/default.rs @@ -1,7 +1,9 @@ use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg}; use clippy_utils::source::snippet_with_macro_callsite; use clippy_utils::ty::{has_drop, is_copy}; -use clippy_utils::{any_parent_is_automatically_derived, contains_name, get_parent_expr, match_def_path, paths}; +use clippy_utils::{ + any_parent_is_automatically_derived, contains_name, get_parent_expr, is_from_proc_macro, match_def_path, paths, +}; use if_chain::if_chain; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -94,6 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for Default { if let QPath::Resolved(None, _path) = qpath; let expr_ty = cx.typeck_results().expr_ty(expr); if let ty::Adt(def, ..) = expr_ty.kind(); + if !is_from_proc_macro(cx, expr); then { // TODO: Work out a way to put "whatever the imported way of referencing // this type in this file" rather than a fully-qualified type. diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index a90f894a7..5d41c6392 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::has_enclosing_paren; -use clippy_utils::ty::{expr_sig, peel_mid_ty_refs, variant_of_res}; +use clippy_utils::ty::{expr_sig, peel_mid_ty_refs, ty_sig, variant_of_res}; use clippy_utils::{get_parent_expr, is_lint_allowed, path_to_local, walk_to_expr_usage}; use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX}; use rustc_data_structures::fx::FxIndexMap; @@ -15,9 +15,9 @@ use rustc_hir::{ use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable, TypeckResults}; +use rustc_middle::ty::{self, Binder, BoundVariableKind, List, Ty, TyCtxt, TypeVisitable, TypeckResults}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::{symbol::sym, Span, Symbol}; +use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP}; use rustc_trait_selection::infer::InferCtxtExt; declare_clippy_lint! { @@ -183,24 +183,24 @@ enum State { }, DerefedBorrow(DerefedBorrow), ExplicitDeref { - // Span and id of the top-level deref expression if the parent expression is a borrow. - deref_span_id: Option<(Span, HirId)>, + mutability: Option, }, ExplicitDerefField { name: Symbol, }, Reborrow { - deref_span: Span, - deref_hir_id: HirId, + mutability: Mutability, + }, + Borrow { + mutability: Mutability, }, - Borrow, } // A reference operation considered by this lint pass enum RefOp { Method(Mutability), Deref, - AddrOf, + AddrOf(Mutability), } struct RefPat { @@ -263,7 +263,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing { )); } else if position.is_deref_stable() { self.state = Some(( - State::ExplicitDeref { deref_span_id: None }, + State::ExplicitDeref { mutability: None }, StateData { span: expr.span, hir_id: expr.hir_id, position }, )); } @@ -289,7 +289,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing { }, )); }, - RefOp::AddrOf => { + RefOp::AddrOf(mutability) => { // Find the number of times the borrow is auto-derefed. let mut iter = adjustments.iter(); let mut deref_count = 0usize; @@ -357,9 +357,13 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing { }), StateData { span: expr.span, hir_id: expr.hir_id, position }, )); - } else if position.is_deref_stable() { + } else if position.is_deref_stable() + // Auto-deref doesn't combine with other adjustments + && next_adjust.map_or(true, |a| matches!(a.kind, Adjust::Deref(_) | Adjust::Borrow(_))) + && iter.all(|a| matches!(a.kind, Adjust::Deref(_) | Adjust::Borrow(_))) + { self.state = Some(( - State::Borrow, + State::Borrow { mutability }, StateData { span: expr.span, hir_id: expr.hir_id, @@ -395,7 +399,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing { data, )); }, - (Some((State::DerefedBorrow(state), data)), RefOp::AddrOf) if state.count != 0 => { + (Some((State::DerefedBorrow(state), data)), RefOp::AddrOf(_)) if state.count != 0 => { self.state = Some(( State::DerefedBorrow(DerefedBorrow { count: state.count - 1, @@ -404,12 +408,12 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing { data, )); }, - (Some((State::DerefedBorrow(state), data)), RefOp::AddrOf) => { + (Some((State::DerefedBorrow(state), data)), RefOp::AddrOf(mutability)) => { let position = data.position; report(cx, expr, State::DerefedBorrow(state), data); if position.is_deref_stable() { self.state = Some(( - State::Borrow, + State::Borrow { mutability }, StateData { span: expr.span, hir_id: expr.hir_id, @@ -430,43 +434,28 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing { )); } else if position.is_deref_stable() { self.state = Some(( - State::ExplicitDeref { deref_span_id: None }, + State::ExplicitDeref { mutability: None }, StateData { span: expr.span, hir_id: expr.hir_id, position }, )); } }, - (Some((State::Borrow, data)), RefOp::Deref) => { + (Some((State::Borrow { mutability }, data)), RefOp::Deref) => { if typeck.expr_ty(sub_expr).is_ref() { - self.state = Some(( - State::Reborrow { - deref_span: expr.span, - deref_hir_id: expr.hir_id, - }, - data, - )); + self.state = Some((State::Reborrow { mutability }, data)); } else { self.state = Some(( State::ExplicitDeref { - deref_span_id: Some((expr.span, expr.hir_id)), + mutability: Some(mutability), }, data, )); } }, - ( - Some(( - State::Reborrow { - deref_span, - deref_hir_id, - }, - data, - )), - RefOp::Deref, - ) => { + (Some((State::Reborrow { mutability }, data)), RefOp::Deref) => { self.state = Some(( State::ExplicitDeref { - deref_span_id: Some((deref_span, deref_hir_id)), + mutability: Some(mutability), }, data, )); @@ -573,7 +562,7 @@ fn try_parse_ref_op<'tcx>( ExprKind::Unary(UnOp::Deref, sub_expr) if !typeck.expr_ty(sub_expr).is_unsafe_ptr() => { return Some((RefOp::Deref, sub_expr)); }, - ExprKind::AddrOf(BorrowKind::Ref, _, sub_expr) => return Some((RefOp::AddrOf, sub_expr)), + ExprKind::AddrOf(BorrowKind::Ref, mutability, sub_expr) => return Some((RefOp::AddrOf(mutability), sub_expr)), _ => return None, }; if tcx.is_diagnostic_item(sym::deref_method, def_id) { @@ -609,18 +598,21 @@ enum Position { Postfix, Deref, /// Any other location which will trigger auto-deref to a specific time. - DerefStable(i8), + /// Contains the precedence of the parent expression and whether the target type is sized. + DerefStable(i8, bool), /// Any other location which will trigger auto-reborrowing. + /// Contains the precedence of the parent expression. ReborrowStable(i8), + /// Contains the precedence of the parent expression. Other(i8), } impl Position { fn is_deref_stable(self) -> bool { - matches!(self, Self::DerefStable(_)) + matches!(self, Self::DerefStable(..)) } fn is_reborrow_stable(self) -> bool { - matches!(self, Self::DerefStable(_) | Self::ReborrowStable(_)) + matches!(self, Self::DerefStable(..) | Self::ReborrowStable(_)) } fn can_auto_borrow(self) -> bool { @@ -628,7 +620,7 @@ impl Position { } fn lint_explicit_deref(self) -> bool { - matches!(self, Self::Other(_) | Self::DerefStable(_) | Self::ReborrowStable(_)) + matches!(self, Self::Other(_) | Self::DerefStable(..) | Self::ReborrowStable(_)) } fn precedence(self) -> i8 { @@ -639,7 +631,7 @@ impl Position { | Self::FieldAccess(_) | Self::Postfix => PREC_POSTFIX, Self::Deref => PREC_PREFIX, - Self::DerefStable(p) | Self::ReborrowStable(p) | Self::Other(p) => p, + Self::DerefStable(p, _) | Self::ReborrowStable(p) | Self::Other(p) => p, } } } @@ -659,7 +651,7 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, & } match parent { Node::Local(Local { ty: Some(ty), span, .. }) if span.ctxt() == ctxt => { - Some(binding_ty_auto_deref_stability(ty, precedence)) + Some(binding_ty_auto_deref_stability(cx, ty, precedence, List::empty())) }, Node::Item(&Item { kind: ItemKind::Static(..) | ItemKind::Const(..), @@ -680,11 +672,7 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, & .. }) if span.ctxt() == ctxt => { let ty = cx.tcx.type_of(def_id); - Some(if ty.is_ref() { - Position::DerefStable(precedence) - } else { - Position::Other(precedence) - }) + Some(ty_auto_deref_stability(cx, ty, precedence).position_for_result(cx)) }, Node::Item(&Item { @@ -705,45 +693,38 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, & span, .. }) if span.ctxt() == ctxt => { - let output = cx.tcx.fn_sig(def_id.to_def_id()).skip_binder().output(); - Some(if !output.is_ref() { - Position::Other(precedence) - } else if output.has_placeholders() || output.has_opaque_types() { - Position::ReborrowStable(precedence) - } else { - Position::DerefStable(precedence) - }) + let output = cx + .tcx + .erase_late_bound_regions(cx.tcx.fn_sig(def_id.to_def_id()).output()); + Some(ty_auto_deref_stability(cx, output, precedence).position_for_result(cx)) }, Node::Expr(parent) if parent.span.ctxt() == ctxt => match parent.kind { ExprKind::Ret(_) => { let owner_id = cx.tcx.hir().body_owner(cx.enclosing_body.unwrap()); Some( - if let Node::Expr(Expr { - kind: ExprKind::Closure(&Closure { fn_decl, .. }), - .. - }) = cx.tcx.hir().get(owner_id) + if let Node::Expr( + closure_expr @ Expr { + kind: ExprKind::Closure(closure), + .. + }, + ) = cx.tcx.hir().get(owner_id) { - match fn_decl.output { - FnRetTy::Return(ty) => binding_ty_auto_deref_stability(ty, precedence), - FnRetTy::DefaultReturn(_) => Position::Other(precedence), - } + closure_result_position(cx, closure, cx.typeck_results().expr_ty(closure_expr), precedence) } else { let output = cx .tcx - .fn_sig(cx.tcx.hir().local_def_id(owner_id)) - .skip_binder() - .output(); - if !output.is_ref() { - Position::Other(precedence) - } else if output.has_placeholders() || output.has_opaque_types() { - Position::ReborrowStable(precedence) - } else { - Position::DerefStable(precedence) - } + .erase_late_bound_regions(cx.tcx.fn_sig(cx.tcx.hir().local_def_id(owner_id)).output()); + ty_auto_deref_stability(cx, output, precedence).position_for_result(cx) }, ) }, + ExprKind::Closure(closure) => Some(closure_result_position( + cx, + closure, + cx.typeck_results().expr_ty(parent), + precedence, + )), ExprKind::Call(func, _) if func.hir_id == child_id => { (child_id == e.hir_id).then_some(Position::Callee) }, @@ -755,8 +736,9 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, & .map(|(hir_ty, ty)| match hir_ty { // Type inference for closures can depend on how they're called. Only go by the explicit // types here. - Some(ty) => binding_ty_auto_deref_stability(ty, precedence), - None => param_auto_deref_stability(ty.skip_binder(), precedence), + Some(hir_ty) => binding_ty_auto_deref_stability(cx, hir_ty, precedence, ty.bound_vars()), + None => ty_auto_deref_stability(cx, cx.tcx.erase_late_bound_regions(ty), precedence) + .position_for_arg(), }), ExprKind::MethodCall(_, args, _) => { let id = cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap(); @@ -797,7 +779,12 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, & Position::MethodReceiver } } else { - param_auto_deref_stability(cx.tcx.fn_sig(id).skip_binder().inputs()[i], precedence) + ty_auto_deref_stability( + cx, + cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(id).input(i)), + precedence, + ) + .position_for_arg() } }) }, @@ -808,7 +795,9 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, & .find(|f| f.expr.hir_id == child_id) .zip(variant) .and_then(|(field, variant)| variant.fields.iter().find(|f| f.name == field.ident.name)) - .map(|field| param_auto_deref_stability(cx.tcx.type_of(field.did), precedence)) + .map(|field| { + ty_auto_deref_stability(cx, cx.tcx.type_of(field.did), precedence).position_for_arg() + }) }, ExprKind::Field(child, name) if child.hir_id == e.hir_id => Some(Position::FieldAccess(name.name)), ExprKind::Unary(UnOp::Deref, child) if child.hir_id == e.hir_id => Some(Position::Deref), @@ -831,6 +820,26 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, & (position, adjustments) } +fn closure_result_position<'tcx>( + cx: &LateContext<'tcx>, + closure: &'tcx Closure<'_>, + ty: Ty<'tcx>, + precedence: i8, +) -> Position { + match closure.fn_decl.output { + FnRetTy::Return(hir_ty) => { + if let Some(sig) = ty_sig(cx, ty) + && let Some(output) = sig.output() + { + binding_ty_auto_deref_stability(cx, hir_ty, precedence, output.bound_vars()) + } else { + Position::Other(precedence) + } + }, + FnRetTy::DefaultReturn(_) => Position::Other(precedence), + } +} + // Checks the stability of auto-deref when assigned to a binding with the given explicit type. // // e.g. @@ -840,7 +849,12 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, & // // Here `y1` and `y2` would resolve to different types, so the type `&Box<_>` is not stable when // switching to auto-dereferencing. -fn binding_ty_auto_deref_stability(ty: &hir::Ty<'_>, precedence: i8) -> Position { +fn binding_ty_auto_deref_stability<'tcx>( + cx: &LateContext<'tcx>, + ty: &'tcx hir::Ty<'_>, + precedence: i8, + binder_args: &'tcx List, +) -> Position { let TyKind::Rptr(_, ty) = &ty.kind else { return Position::Other(precedence); }; @@ -870,21 +884,33 @@ fn binding_ty_auto_deref_stability(ty: &hir::Ty<'_>, precedence: i8) -> Position { Position::ReborrowStable(precedence) } else { - Position::DerefStable(precedence) + Position::DerefStable( + precedence, + cx.tcx + .erase_late_bound_regions(Binder::bind_with_vars( + cx.typeck_results().node_type(ty.ty.hir_id), + binder_args, + )) + .is_sized(cx.tcx.at(DUMMY_SP), cx.param_env.without_caller_bounds()), + ) } }, - TyKind::Slice(_) - | TyKind::Array(..) - | TyKind::BareFn(_) - | TyKind::Never + TyKind::Slice(_) => Position::DerefStable(precedence, false), + TyKind::Array(..) | TyKind::Ptr(_) | TyKind::BareFn(_) => Position::DerefStable(precedence, true), + TyKind::Never | TyKind::Tup(_) - | TyKind::Ptr(_) - | TyKind::TraitObject(..) - | TyKind::Path(_) => Position::DerefStable(precedence), - TyKind::OpaqueDef(..) - | TyKind::Infer - | TyKind::Typeof(..) - | TyKind::Err => Position::ReborrowStable(precedence), + | TyKind::Path(_) => Position::DerefStable( + precedence, + cx.tcx + .erase_late_bound_regions(Binder::bind_with_vars( + cx.typeck_results().node_type(ty.ty.hir_id), + binder_args, + )) + .is_sized(cx.tcx.at(DUMMY_SP), cx.param_env.without_caller_bounds()), + ), + TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => { + Position::ReborrowStable(precedence) + }, }; } } @@ -920,10 +946,39 @@ fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool { v.0 } +struct TyPosition<'tcx> { + position: Position, + ty: Option>, +} +impl From for TyPosition<'_> { + fn from(position: Position) -> Self { + Self { position, ty: None } + } +} +impl<'tcx> TyPosition<'tcx> { + fn new_deref_stable_for_result(precedence: i8, ty: Ty<'tcx>) -> Self { + Self { + position: Position::ReborrowStable(precedence), + ty: Some(ty), + } + } + fn position_for_result(self, cx: &LateContext<'tcx>) -> Position { + match (self.position, self.ty) { + (Position::ReborrowStable(precedence), Some(ty)) => { + Position::DerefStable(precedence, ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env)) + }, + (position, _) => position, + } + } + fn position_for_arg(self) -> Position { + self.position + } +} + // Checks whether a type is stable when switching to auto dereferencing, -fn param_auto_deref_stability(ty: Ty<'_>, precedence: i8) -> Position { +fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedence: i8) -> TyPosition<'tcx> { let ty::Ref(_, mut ty, _) = *ty.kind() else { - return Position::Other(precedence); + return Position::Other(precedence).into(); }; loop { @@ -932,35 +987,38 @@ fn param_auto_deref_stability(ty: Ty<'_>, precedence: i8) -> Position { ty = ref_ty; continue; }, - ty::Infer(_) - | ty::Error(_) - | ty::Param(_) - | ty::Bound(..) - | ty::Opaque(..) - | ty::Placeholder(_) - | ty::Dynamic(..) => Position::ReborrowStable(precedence), - ty::Adt(..) if ty.has_placeholders() || ty.has_param_types_or_consts() => { - Position::ReborrowStable(precedence) + ty::Param(_) => TyPosition::new_deref_stable_for_result(precedence, ty), + ty::Infer(_) | ty::Error(_) | ty::Bound(..) | ty::Opaque(..) | ty::Placeholder(_) | ty::Dynamic(..) => { + Position::ReborrowStable(precedence).into() }, - ty::Adt(..) - | ty::Bool + ty::Adt(..) if ty.has_placeholders() || ty.has_opaque_types() => { + Position::ReborrowStable(precedence).into() + }, + ty::Adt(_, substs) if substs.has_param_types_or_consts() => { + TyPosition::new_deref_stable_for_result(precedence, ty) + }, + ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) - | ty::Float(_) - | ty::Foreign(_) - | ty::Str | ty::Array(..) - | ty::Slice(..) + | ty::Float(_) | ty::RawPtr(..) + | ty::FnPtr(_) => Position::DerefStable(precedence, true).into(), + ty::Str | ty::Slice(..) => Position::DerefStable(precedence, false).into(), + ty::Adt(..) + | ty::Foreign(_) | ty::FnDef(..) - | ty::FnPtr(_) - | ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) + | ty::Closure(..) | ty::Never | ty::Tuple(_) - | ty::Projection(_) => Position::DerefStable(precedence), + | ty::Projection(_) => Position::DerefStable( + precedence, + ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env.without_caller_bounds()), + ) + .into(), }; } } @@ -1040,34 +1098,64 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data diag.span_suggestion(data.span, "change this to", sugg, app); }); }, - State::ExplicitDeref { deref_span_id } => { - let (span, hir_id, precedence) = if let Some((span, hir_id)) = deref_span_id + State::ExplicitDeref { mutability } => { + if matches!( + expr.kind, + ExprKind::Block(..) + | ExprKind::ConstBlock(_) + | ExprKind::If(..) + | ExprKind::Loop(..) + | ExprKind::Match(..) + ) && matches!(data.position, Position::DerefStable(_, true)) + { + // Rustc bug: auto deref doesn't work on block expression when targeting sized types. + return; + } + + let (prefix, precedence) = if let Some(mutability) = mutability && !cx.typeck_results().expr_ty(expr).is_ref() { - (span, hir_id, PREC_PREFIX) + let prefix = match mutability { + Mutability::Not => "&", + Mutability::Mut => "&mut ", + }; + (prefix, 0) } else { - (data.span, data.hir_id, data.position.precedence()) + ("", data.position.precedence()) }; span_lint_hir_and_then( cx, EXPLICIT_AUTO_DEREF, - hir_id, - span, + data.hir_id, + data.span, "deref which would be done by auto-deref", |diag| { let mut app = Applicability::MachineApplicable; - let (snip, snip_is_macro) = snippet_with_context(cx, expr.span, span.ctxt(), "..", &mut app); + let (snip, snip_is_macro) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app); let sugg = if !snip_is_macro && expr.precedence().order() < precedence && !has_enclosing_paren(&snip) { - format!("({})", snip) + format!("{}({})", prefix, snip) } else { - snip.into() + format!("{}{}", prefix, snip) }; - diag.span_suggestion(span, "try this", sugg, app); + diag.span_suggestion(data.span, "try this", sugg, app); }, ); }, State::ExplicitDerefField { .. } => { + if matches!( + expr.kind, + ExprKind::Block(..) + | ExprKind::ConstBlock(_) + | ExprKind::If(..) + | ExprKind::Loop(..) + | ExprKind::Match(..) + ) && matches!(data.position, Position::DerefStable(_, true)) + { + // Rustc bug: auto deref doesn't work on block expression when targeting sized types. + return; + } + span_lint_hir_and_then( cx, EXPLICIT_AUTO_DEREF, @@ -1081,7 +1169,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data }, ); }, - State::Borrow | State::Reborrow { .. } => (), + State::Borrow { .. } | State::Reborrow { .. } => (), } } diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/disallowed_names.rs similarity index 72% rename from clippy_lints/src/blacklisted_name.rs rename to clippy_lints/src/disallowed_names.rs index 1600fb25d..6e6615f08 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/disallowed_names.rs @@ -6,7 +6,7 @@ use rustc_session::{declare_tool_lint, impl_lint_pass}; declare_clippy_lint! { /// ### What it does - /// Checks for usage of blacklisted names for variables, such + /// Checks for usage of disallowed names for variables, such /// as `foo`. /// /// ### Why is this bad? @@ -18,21 +18,21 @@ declare_clippy_lint! { /// let foo = 3.14; /// ``` #[clippy::version = "pre 1.29.0"] - pub BLACKLISTED_NAME, + pub DISALLOWED_NAMES, style, - "usage of a blacklisted/placeholder name" + "usage of a disallowed/placeholder name" } #[derive(Clone, Debug)] -pub struct BlacklistedName { - blacklist: FxHashSet, +pub struct DisallowedNames { + disallow: FxHashSet, test_modules_deep: u32, } -impl BlacklistedName { - pub fn new(blacklist: FxHashSet) -> Self { +impl DisallowedNames { + pub fn new(disallow: FxHashSet) -> Self { Self { - blacklist, + disallow, test_modules_deep: 0, } } @@ -42,9 +42,9 @@ impl BlacklistedName { } } -impl_lint_pass!(BlacklistedName => [BLACKLISTED_NAME]); +impl_lint_pass!(DisallowedNames => [DISALLOWED_NAMES]); -impl<'tcx> LateLintPass<'tcx> for BlacklistedName { +impl<'tcx> LateLintPass<'tcx> for DisallowedNames { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { if is_test_module_or_function(cx.tcx, item) { self.test_modules_deep = self.test_modules_deep.saturating_add(1); @@ -58,12 +58,12 @@ impl<'tcx> LateLintPass<'tcx> for BlacklistedName { } if let PatKind::Binding(.., ident, _) = pat.kind { - if self.blacklist.contains(&ident.name.to_string()) { + if self.disallow.contains(&ident.name.to_string()) { span_lint( cx, - BLACKLISTED_NAME, + DISALLOWED_NAMES, ident.span, - &format!("use of a blacklisted/placeholder name `{}`", ident.name), + &format!("use of a disallowed/placeholder name `{}`", ident.name), ); } } diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index db0166da5..01cefe4af 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -1,4 +1,5 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note}; +use clippy_utils::is_span_if; use clippy_utils::source::snippet_opt; use if_chain::if_chain; use rustc_ast::ast::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp}; @@ -297,12 +298,11 @@ fn check_array(cx: &EarlyContext<'_>, expr: &Expr) { fn check_missing_else(cx: &EarlyContext<'_>, first: &Expr, second: &Expr) { if_chain! { if !first.span.from_expansion() && !second.span.from_expansion(); - if let ExprKind::If(cond_expr, ..) = &first.kind; + if matches!(first.kind, ExprKind::If(..)); if is_block(second) || is_if(second); // Proc-macros can give weird spans. Make sure this is actually an `if`. - if let Some(if_snip) = snippet_opt(cx, first.span.until(cond_expr.span)); - if if_snip.starts_with("if"); + if is_span_if(cx, first.span); // If there is a line break between the two expressions, don't lint. // If there is a non-whitespace character, this span came from a proc-macro. diff --git a/clippy_lints/src/from_str_radix_10.rs b/clippy_lints/src/from_str_radix_10.rs index 57b075132..74941d817 100644 --- a/clippy_lints/src/from_str_radix_10.rs +++ b/clippy_lints/src/from_str_radix_10.rs @@ -46,7 +46,7 @@ declare_lint_pass!(FromStrRadix10 => [FROM_STR_RADIX_10]); impl<'tcx> LateLintPass<'tcx> for FromStrRadix10 { fn check_expr(&mut self, cx: &LateContext<'tcx>, exp: &Expr<'tcx>) { if_chain! { - if let ExprKind::Call(maybe_path, arguments) = &exp.kind; + if let ExprKind::Call(maybe_path, [src, radix]) = &exp.kind; if let ExprKind::Path(QPath::TypeRelative(ty, pathseg)) = &maybe_path.kind; // check if the first part of the path is some integer primitive @@ -60,20 +60,19 @@ impl<'tcx> LateLintPass<'tcx> for FromStrRadix10 { if pathseg.ident.name.as_str() == "from_str_radix"; // check if the second argument is a primitive `10` - if arguments.len() == 2; - if let ExprKind::Lit(lit) = &arguments[1].kind; + if let ExprKind::Lit(lit) = &radix.kind; if let rustc_ast::ast::LitKind::Int(10, _) = lit.node; then { - let expr = if let ExprKind::AddrOf(_, _, expr) = &arguments[0].kind { + let expr = if let ExprKind::AddrOf(_, _, expr) = &src.kind { let ty = cx.typeck_results().expr_ty(expr); if is_ty_stringish(cx, ty) { expr } else { - &arguments[0] + &src } } else { - &arguments[0] + &src }; let sugg = Sugg::hir_with_applicability( diff --git a/clippy_lints/src/lib.register_all.rs b/clippy_lints/src/lib.register_all.rs index 0ba9b7ae7..01082cc8e 100644 --- a/clippy_lints/src/lib.register_all.rs +++ b/clippy_lints/src/lib.register_all.rs @@ -15,11 +15,10 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(await_holding_invalid::AWAIT_HOLDING_INVALID_TYPE), LintId::of(await_holding_invalid::AWAIT_HOLDING_LOCK), LintId::of(await_holding_invalid::AWAIT_HOLDING_REFCELL_REF), - LintId::of(blacklisted_name::BLACKLISTED_NAME), LintId::of(blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS), LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON), - LintId::of(booleans::LOGIC_BUG), LintId::of(booleans::NONMINIMAL_BOOL), + LintId::of(booleans::OVERLY_COMPLEX_BOOL_EXPR), LintId::of(borrow_deref_ref::BORROW_DEREF_REF), LintId::of(bytes_count_to_len::BYTES_COUNT_TO_LEN), LintId::of(casts::CAST_ABS_TO_UNSIGNED), @@ -46,6 +45,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(derive::DERIVE_ORD_XOR_PARTIAL_ORD), LintId::of(derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ), LintId::of(disallowed_methods::DISALLOWED_METHODS), + LintId::of(disallowed_names::DISALLOWED_NAMES), LintId::of(disallowed_types::DISALLOWED_TYPES), LintId::of(doc::MISSING_SAFETY_DOC), LintId::of(doc::NEEDLESS_DOCTEST_MAIN), @@ -144,7 +144,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(matches::MATCH_STR_CASE_MISMATCH), LintId::of(matches::NEEDLESS_MATCH), LintId::of(matches::REDUNDANT_PATTERN_MATCHING), - LintId::of(matches::SIGNIFICANT_DROP_IN_SCRUTINEE), LintId::of(matches::SINGLE_MATCH), LintId::of(matches::WILDCARD_IN_OR_PATTERNS), LintId::of(mem_replace::MEM_REPLACE_OPTION_WITH_NONE), @@ -267,6 +266,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP), LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL), LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL), + LintId::of(partialeq_to_none::PARTIALEQ_TO_NONE), LintId::of(precedence::PRECEDENCE), LintId::of(ptr::CMP_NULL), LintId::of(ptr::INVALID_NULL_PTR_USAGE), diff --git a/clippy_lints/src/lib.register_correctness.rs b/clippy_lints/src/lib.register_correctness.rs index 9975859c5..006275d13 100644 --- a/clippy_lints/src/lib.register_correctness.rs +++ b/clippy_lints/src/lib.register_correctness.rs @@ -8,7 +8,7 @@ store.register_group(true, "clippy::correctness", Some("clippy_correctness"), ve LintId::of(attrs::DEPRECATED_SEMVER), LintId::of(attrs::MISMATCHED_TARGET_OS), LintId::of(attrs::USELESS_ATTRIBUTE), - LintId::of(booleans::LOGIC_BUG), + LintId::of(booleans::OVERLY_COMPLEX_BOOL_EXPR), LintId::of(casts::CAST_REF_TO_MUT), LintId::of(casts::CAST_SLICE_DIFFERENT_SIZES), LintId::of(copies::IFS_SAME_COND), diff --git a/clippy_lints/src/lib.register_lints.rs b/clippy_lints/src/lib.register_lints.rs index 99bde35cf..c540573b8 100644 --- a/clippy_lints/src/lib.register_lints.rs +++ b/clippy_lints/src/lib.register_lints.rs @@ -55,11 +55,10 @@ store.register_lints(&[ await_holding_invalid::AWAIT_HOLDING_INVALID_TYPE, await_holding_invalid::AWAIT_HOLDING_LOCK, await_holding_invalid::AWAIT_HOLDING_REFCELL_REF, - blacklisted_name::BLACKLISTED_NAME, blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS, bool_assert_comparison::BOOL_ASSERT_COMPARISON, - booleans::LOGIC_BUG, booleans::NONMINIMAL_BOOL, + booleans::OVERLY_COMPLEX_BOOL_EXPR, borrow_as_ptr::BORROW_AS_PTR, borrow_deref_ref::BORROW_DEREF_REF, bytecount::NAIVE_BYTECOUNT, @@ -116,6 +115,7 @@ store.register_lints(&[ derive::EXPL_IMPL_CLONE_ON_COPY, derive::UNSAFE_DERIVE_DESERIALIZE, disallowed_methods::DISALLOWED_METHODS, + disallowed_names::DISALLOWED_NAMES, disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS, disallowed_types::DISALLOWED_TYPES, doc::DOC_MARKDOWN, @@ -244,6 +244,7 @@ store.register_lints(&[ manual_assert::MANUAL_ASSERT, manual_async_fn::MANUAL_ASYNC_FN, manual_bits::MANUAL_BITS, + manual_instant_elapsed::MANUAL_INSTANT_ELAPSED, manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE, manual_ok_or::MANUAL_OK_OR, manual_rem_euclid::MANUAL_REM_EUCLID, @@ -453,6 +454,7 @@ store.register_lints(&[ panic_unimplemented::UNIMPLEMENTED, panic_unimplemented::UNREACHABLE, partialeq_ne_impl::PARTIALEQ_NE_IMPL, + partialeq_to_none::PARTIALEQ_TO_NONE, pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE, pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF, path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE, diff --git a/clippy_lints/src/lib.register_nursery.rs b/clippy_lints/src/lib.register_nursery.rs index 642d62997..91210b23a 100644 --- a/clippy_lints/src/lib.register_nursery.rs +++ b/clippy_lints/src/lib.register_nursery.rs @@ -13,6 +13,7 @@ store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![ LintId::of(future_not_send::FUTURE_NOT_SEND), LintId::of(index_refutable_slice::INDEX_REFUTABLE_SLICE), LintId::of(let_if_seq::USELESS_LET_IF_SEQ), + LintId::of(matches::SIGNIFICANT_DROP_IN_SCRUTINEE), LintId::of(methods::ITER_WITH_DRAIN), LintId::of(missing_const_for_fn::MISSING_CONST_FOR_FN), LintId::of(mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL), diff --git a/clippy_lints/src/lib.register_pedantic.rs b/clippy_lints/src/lib.register_pedantic.rs index a1b546658..bd7d1a15a 100644 --- a/clippy_lints/src/lib.register_pedantic.rs +++ b/clippy_lints/src/lib.register_pedantic.rs @@ -49,6 +49,7 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![ LintId::of(loops::EXPLICIT_ITER_LOOP), LintId::of(macro_use::MACRO_USE_IMPORTS), LintId::of(manual_assert::MANUAL_ASSERT), + LintId::of(manual_instant_elapsed::MANUAL_INSTANT_ELAPSED), LintId::of(manual_ok_or::MANUAL_OK_OR), LintId::of(matches::MATCH_BOOL), LintId::of(matches::MATCH_ON_VEC_ITEMS), diff --git a/clippy_lints/src/lib.register_style.rs b/clippy_lints/src/lib.register_style.rs index e95bab1d0..bfa654238 100644 --- a/clippy_lints/src/lib.register_style.rs +++ b/clippy_lints/src/lib.register_style.rs @@ -4,7 +4,6 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![ LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS), - LintId::of(blacklisted_name::BLACKLISTED_NAME), LintId::of(blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS), LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON), LintId::of(casts::FN_TO_NUMERIC_CAST), @@ -17,6 +16,7 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![ LintId::of(dereference::NEEDLESS_BORROW), LintId::of(derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ), LintId::of(disallowed_methods::DISALLOWED_METHODS), + LintId::of(disallowed_names::DISALLOWED_NAMES), LintId::of(disallowed_types::DISALLOWED_TYPES), LintId::of(doc::MISSING_SAFETY_DOC), LintId::of(doc::NEEDLESS_DOCTEST_MAIN), @@ -100,6 +100,7 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![ LintId::of(operators::ASSIGN_OP_PATTERN), LintId::of(operators::OP_REF), LintId::of(operators::PTR_EQ), + LintId::of(partialeq_to_none::PARTIALEQ_TO_NONE), LintId::of(ptr::CMP_NULL), LintId::of(ptr::PTR_ARG), LintId::of(question_mark::QUESTION_MARK), diff --git a/clippy_lints/src/lib.register_suspicious.rs b/clippy_lints/src/lib.register_suspicious.rs index f7558f870..964992bd9 100644 --- a/clippy_lints/src/lib.register_suspicious.rs +++ b/clippy_lints/src/lib.register_suspicious.rs @@ -22,7 +22,6 @@ store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), vec! LintId::of(loops::EMPTY_LOOP), LintId::of(loops::FOR_LOOPS_OVER_FALLIBLES), LintId::of(loops::MUT_RANGE_BOUND), - LintId::of(matches::SIGNIFICANT_DROP_IN_SCRUTINEE), LintId::of(methods::NO_EFFECT_REPLACE), LintId::of(methods::SUSPICIOUS_MAP), LintId::of(mut_key::MUTABLE_KEY_TYPE), diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index eb3841272..2975399a8 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -178,7 +178,6 @@ mod assertions_on_result_states; mod async_yields_async; mod attrs; mod await_holding_invalid; -mod blacklisted_name; mod blocks_in_if_conditions; mod bool_assert_comparison; mod booleans; @@ -206,6 +205,7 @@ mod dereference; mod derivable_impls; mod derive; mod disallowed_methods; +mod disallowed_names; mod disallowed_script_idents; mod disallowed_types; mod doc; @@ -274,6 +274,7 @@ mod main_recursion; mod manual_assert; mod manual_async_fn; mod manual_bits; +mod manual_instant_elapsed; mod manual_non_exhaustive; mod manual_ok_or; mod manual_rem_euclid; @@ -332,6 +333,7 @@ mod overflow_check_conditional; mod panic_in_result_fn; mod panic_unimplemented; mod partialeq_ne_impl; +mod partialeq_to_none; mod pass_by_ref_or_value; mod path_buf_push_overwrite; mod pattern_type_mismatch; @@ -487,7 +489,7 @@ pub fn read_conf(sess: &Session) -> Conf { }, }; - let TryConf { conf, errors } = utils::conf::read(&file_name); + let TryConf { conf, errors, warnings } = utils::conf::read(&file_name); // all conf errors are non-fatal, we just use the default conf in case of error for error in errors { sess.err(&format!( @@ -497,6 +499,15 @@ pub fn read_conf(sess: &Session) -> Conf { )); } + for warning in warnings { + sess.struct_warn(&format!( + "error reading Clippy's configuration file `{}`: {}", + file_name.display(), + format_error(warning) + )) + .emit(); + } + conf } @@ -675,8 +686,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(swap::Swap)); store.register_late_pass(|| Box::new(overflow_check_conditional::OverflowCheckConditional)); store.register_late_pass(|| Box::new(new_without_default::NewWithoutDefault::default())); - let blacklisted_names = conf.blacklisted_names.iter().cloned().collect::>(); - store.register_late_pass(move || Box::new(blacklisted_name::BlacklistedName::new(blacklisted_names.clone()))); + let disallowed_names = conf.disallowed_names.iter().cloned().collect::>(); + store.register_late_pass(move || Box::new(disallowed_names::DisallowedNames::new(disallowed_names.clone()))); let too_many_arguments_threshold = conf.too_many_arguments_threshold; let too_many_lines_threshold = conf.too_many_lines_threshold; store.register_late_pass(move || { @@ -921,6 +932,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move || Box::new(operators::Operators::new(verbose_bit_mask_threshold))); store.register_late_pass(|| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked)); store.register_late_pass(|| Box::new(std_instead_of_core::StdReexports::default())); + store.register_late_pass(|| Box::new(manual_instant_elapsed::ManualInstantElapsed)); + store.register_late_pass(|| Box::new(partialeq_to_none::PartialeqToNone)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/loops/manual_memcpy.rs b/clippy_lints/src/loops/manual_memcpy.rs index b31015d19..a65df48e4 100644 --- a/clippy_lints/src/loops/manual_memcpy.rs +++ b/clippy_lints/src/loops/manual_memcpy.rs @@ -119,11 +119,9 @@ fn build_manual_memcpy_suggestion<'tcx>( let print_limit = |end: &Expr<'_>, end_str: &str, base: &Expr<'_>, sugg: MinifyingSugg<'static>| { if_chain! { - if let ExprKind::MethodCall(method, len_args, _) = end.kind; + if let ExprKind::MethodCall(method, [recv], _) = end.kind; if method.ident.name == sym::len; - if len_args.len() == 1; - if let Some(arg) = len_args.get(0); - if path_to_local(arg) == path_to_local(base); + if path_to_local(recv) == path_to_local(base); then { if sugg.to_string() == end_str { sugg::EMPTY.into() @@ -343,10 +341,8 @@ fn get_slice_like_element_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Opti fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> { if_chain! { - if let ExprKind::MethodCall(method, args, _) = expr.kind; + if let ExprKind::MethodCall(method, [arg], _) = expr.kind; if method.ident.name == sym::clone; - if args.len() == 1; - if let Some(arg) = args.get(0); then { arg } else { expr } } } diff --git a/clippy_lints/src/loops/needless_range_loop.rs b/clippy_lints/src/loops/needless_range_loop.rs index a7ef562b2..7ca4a7c4e 100644 --- a/clippy_lints/src/loops/needless_range_loop.rs +++ b/clippy_lints/src/loops/needless_range_loop.rs @@ -188,10 +188,9 @@ pub(super) fn check<'tcx>( fn is_len_call(expr: &Expr<'_>, var: Symbol) -> bool { if_chain! { - if let ExprKind::MethodCall(method, len_args, _) = expr.kind; - if len_args.len() == 1; + if let ExprKind::MethodCall(method, [recv], _) = expr.kind; if method.ident.name == sym::len; - if let ExprKind::Path(QPath::Resolved(_, path)) = len_args[0].kind; + if let ExprKind::Path(QPath::Resolved(_, path)) = recv.kind; if path.segments.len() == 1; if path.segments[0].ident.name == var; then { diff --git a/clippy_lints/src/manual_instant_elapsed.rs b/clippy_lints/src/manual_instant_elapsed.rs new file mode 100644 index 000000000..331cda1db --- /dev/null +++ b/clippy_lints/src/manual_instant_elapsed.rs @@ -0,0 +1,69 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +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; + +declare_clippy_lint! { + /// ### What it does + /// Lints subtraction between `Instant::now()` and another `Instant`. + /// + /// ### Why is this bad? + /// It is easy to accidentally write `prev_instant - Instant::now()`, which will always be 0ns + /// as `Instant` subtraction saturates. + /// + /// `prev_instant.elapsed()` also more clearly signals intention. + /// + /// ### Example + /// ```rust + /// use std::time::Instant; + /// let prev_instant = Instant::now(); + /// let duration = Instant::now() - prev_instant; + /// ``` + /// Use instead: + /// ```rust + /// use std::time::Instant; + /// let prev_instant = Instant::now(); + /// let duration = prev_instant.elapsed(); + /// ``` + #[clippy::version = "1.64.0"] + pub MANUAL_INSTANT_ELAPSED, + pedantic, + "subtraction between `Instant::now()` and previous `Instant`" +} + +declare_lint_pass!(ManualInstantElapsed => [MANUAL_INSTANT_ELAPSED]); + +impl LateLintPass<'_> for ManualInstantElapsed { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { + if let ExprKind::Binary(Spanned {node: BinOpKind::Sub, ..}, lhs, rhs) = expr.kind + && check_instant_now_call(cx, lhs) + && let ty_resolved = cx.typeck_results().expr_ty(rhs) + && let rustc_middle::ty::Adt(def, _) = ty_resolved.kind() + && clippy_utils::match_def_path(cx, def.did(), &clippy_utils::paths::INSTANT) + && let Some(sugg) = clippy_utils::sugg::Sugg::hir_opt(cx, rhs) + { + span_lint_and_sugg( + cx, + MANUAL_INSTANT_ELAPSED, + expr.span, + "manual implementation of `Instant::elapsed`", + "try", + format!("{}.elapsed()", sugg.maybe_par()), + Applicability::MachineApplicable, + ); + } + } +} + +fn check_instant_now_call(cx: &LateContext<'_>, expr_block: &'_ Expr<'_>) -> bool { + if let ExprKind::Call(fn_expr, []) = expr_block.kind + && let Some(fn_id) = clippy_utils::path_def_id(cx, fn_expr) + && clippy_utils::match_def_path(cx, fn_id, &clippy_utils::paths::INSTANT_NOW) + { + true + } else { + false + } +} diff --git a/clippy_lints/src/manual_ok_or.rs b/clippy_lints/src/manual_ok_or.rs index 9abf2507b..cf5004399 100644 --- a/clippy_lints/src/manual_ok_or.rs +++ b/clippy_lints/src/manual_ok_or.rs @@ -47,17 +47,14 @@ impl<'tcx> LateLintPass<'tcx> for ManualOkOr { } if_chain! { - if let ExprKind::MethodCall(method_segment, args, _) = scrutinee.kind; + if let ExprKind::MethodCall(method_segment, [receiver, or_expr, map_expr], _) = scrutinee.kind; if method_segment.ident.name == sym!(map_or); - if args.len() == 3; - let method_receiver = &args[0]; - let ty = cx.typeck_results().expr_ty(method_receiver); + let ty = cx.typeck_results().expr_ty(receiver); if is_type_diagnostic_item(cx, ty, sym::Option); - let or_expr = &args[1]; - if is_ok_wrapping(cx, &args[2]); + if is_ok_wrapping(cx, map_expr); if let ExprKind::Call(Expr { kind: ExprKind::Path(err_path), .. }, &[ref err_arg]) = or_expr.kind; if is_lang_ctor(cx, err_path, ResultErr); - if let Some(method_receiver_snippet) = snippet_opt(cx, method_receiver.span); + if let Some(method_receiver_snippet) = snippet_opt(cx, receiver.span); if let Some(err_arg_snippet) = snippet_opt(cx, err_arg.span); if let Some(indent) = indent_of(cx, scrutinee.span); then { diff --git a/clippy_lints/src/map_err_ignore.rs b/clippy_lints/src/map_err_ignore.rs index 21d0e19eb..1e542447c 100644 --- a/clippy_lints/src/map_err_ignore.rs +++ b/clippy_lints/src/map_err_ignore.rs @@ -113,10 +113,10 @@ impl<'tcx> LateLintPass<'tcx> for MapErrIgnore { } // check if this is a method call (e.g. x.foo()) - if let ExprKind::MethodCall(method, args, _) = e.kind { + if let ExprKind::MethodCall(method, [_, arg], _) = e.kind { // only work if the method name is `map_err` and there are only 2 arguments (e.g. x.map_err(|_|[1] // Enum::Variant[2])) - if method.ident.as_str() == "map_err" && args.len() == 2 { + if method.ident.name == sym!(map_err) { // make sure the first argument is a closure, and grab the CaptureRef, BodyId, and fn_decl_span // fields if let ExprKind::Closure(&Closure { @@ -124,7 +124,7 @@ impl<'tcx> LateLintPass<'tcx> for MapErrIgnore { body, fn_decl_span, .. - }) = args[1].kind + }) = arg.kind { // check if this is by Reference (meaning there's no move statement) if capture_clause == CaptureBy::Ref { diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index af9d948af..6db852c3f 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -97,11 +97,7 @@ declare_clippy_lint! { declare_lint_pass!(MapUnit => [OPTION_MAP_UNIT_FN, RESULT_MAP_UNIT_FN]); fn is_unit_type(ty: Ty<'_>) -> bool { - match ty.kind() { - ty::Tuple(slice) => slice.is_empty(), - ty::Never => true, - _ => false, - } + ty.is_unit() || ty.is_never() } fn is_unit_function(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { diff --git a/clippy_lints/src/matches/match_as_ref.rs b/clippy_lints/src/matches/match_as_ref.rs index d914eba01..a0efdecec 100644 --- a/clippy_lints/src/matches/match_as_ref.rs +++ b/clippy_lints/src/matches/match_as_ref.rs @@ -72,10 +72,10 @@ fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option LateLintPass<'tcx> for Matches { let from_expansion = expr.span.from_expansion(); if let ExprKind::Match(ex, arms, source) = expr.kind { - if source == MatchSource::Normal && !span_starts_with(cx, expr.span, "match") { + if source == MatchSource::Normal && !is_span_match(cx, expr.span) { return; } if matches!(source, MatchSource::Normal | MatchSource::ForLoopDesugar) { diff --git a/clippy_lints/src/matches/try_err.rs b/clippy_lints/src/matches/try_err.rs index 0491a0679..663277d11 100644 --- a/clippy_lints/src/matches/try_err.rs +++ b/clippy_lints/src/matches/try_err.rs @@ -23,12 +23,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine // val, // }; if_chain! { - if let ExprKind::Call(match_fun, try_args) = scrutinee.kind; + if let ExprKind::Call(match_fun, [try_arg, ..]) = scrutinee.kind; if let ExprKind::Path(ref match_fun_path) = match_fun.kind; if matches!(match_fun_path, QPath::LangItem(LangItem::TryTraitBranch, ..)); - if let Some(try_arg) = try_args.get(0); - if let ExprKind::Call(err_fun, err_args) = try_arg.kind; - if let Some(err_arg) = err_args.get(0); + if let ExprKind::Call(err_fun, [err_arg, ..]) = try_arg.kind; if let ExprKind::Path(ref err_fun_path) = err_fun.kind; if is_lang_ctor(cx, err_fun_path, ResultErr); if let Some(return_ty) = find_return_type(cx, &expr.kind); diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index 41073d40f..cad3ea2a1 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -163,8 +163,7 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<' } if_chain! { - if let ExprKind::Call(repl_func, repl_args) = src.kind; - if repl_args.is_empty(); + if let ExprKind::Call(repl_func, []) = src.kind; if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind; if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id(); then { @@ -246,11 +245,10 @@ impl<'tcx> LateLintPass<'tcx> for MemReplace { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { // Check that `expr` is a call to `mem::replace()` - if let ExprKind::Call(func, func_args) = expr.kind; + if let ExprKind::Call(func, [dest, src]) = expr.kind; if let ExprKind::Path(ref func_qpath) = func.kind; if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); if cx.tcx.is_diagnostic_item(sym::mem_replace, def_id); - if let [dest, src] = func_args; then { check_replace_option_with_none(cx, src, dest, expr.span); check_replace_with_uninit(cx, src, dest, expr.span); diff --git a/clippy_lints/src/methods/clone_on_copy.rs b/clippy_lints/src/methods/clone_on_copy.rs index 0b38a0720..60e1355f9 100644 --- a/clippy_lints/src/methods/clone_on_copy.rs +++ b/clippy_lints/src/methods/clone_on_copy.rs @@ -4,7 +4,7 @@ use clippy_utils::source::snippet_with_context; use clippy_utils::sugg; use clippy_utils::ty::is_copy; use rustc_errors::Applicability; -use rustc_hir::{BindingAnnotation, Expr, ExprKind, MatchSource, Node, PatKind}; +use rustc_hir::{BindingAnnotation, Expr, ExprKind, MatchSource, Node, PatKind, QPath}; use rustc_lint::LateContext; use rustc_middle::ty::{self, adjustment::Adjust}; use rustc_span::symbol::{sym, Symbol}; @@ -86,6 +86,11 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol, { return; }, + // ? is a Call, makes sure not to rec *x?, but rather (*x)? + ExprKind::Call(hir_callee, _) => matches!( + hir_callee.kind, + ExprKind::Path(QPath::LangItem(rustc_hir::LangItem::TryTraitBranch, _, _)) + ), ExprKind::MethodCall(_, [self_arg, ..], _) if expr.hir_id == self_arg.hir_id => true, ExprKind::Match(_, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar) | ExprKind::Field(..) diff --git a/clippy_lints/src/methods/expect_used.rs b/clippy_lints/src/methods/expect_used.rs index fbc3348f1..5ef08ca62 100644 --- a/clippy_lints/src/methods/expect_used.rs +++ b/clippy_lints/src/methods/expect_used.rs @@ -12,9 +12,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs(); let mess = if is_type_diagnostic_item(cx, obj_ty, sym::Option) { - Some((EXPECT_USED, "an Option", "None")) + Some((EXPECT_USED, "an Option", "None", "")) } else if is_type_diagnostic_item(cx, obj_ty, sym::Result) { - Some((EXPECT_USED, "a Result", "Err")) + Some((EXPECT_USED, "a Result", "Err", "an ")) } else { None }; @@ -23,14 +23,14 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr return; } - if let Some((lint, kind, none_value)) = mess { + if let Some((lint, kind, none_value, none_prefix)) = mess { span_lint_and_help( cx, lint, expr.span, - &format!("used `expect()` on `{}` value", kind,), + &format!("used `expect()` on `{kind}` value"), None, - &format!("if this value is an `{}`, it will panic", none_value,), + &format!("if this value is {none_prefix}`{none_value}`, it will panic"), ); } } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 202fbc1f7..5ac6b09f0 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -204,6 +204,17 @@ declare_clippy_lint! { /// option.expect("more helpful message"); /// result.expect("more helpful message"); /// ``` + /// + /// If [expect_used](#expect_used) is enabled, instead: + /// ```rust,ignore + /// # let option = Some(1); + /// # let result: Result = Ok(1); + /// option?; + /// + /// // or + /// + /// result?; + /// ``` #[clippy::version = "1.45.0"] pub UNWRAP_USED, restriction, diff --git a/clippy_lints/src/methods/unwrap_used.rs b/clippy_lints/src/methods/unwrap_used.rs index 5c7610149..ce1a52e54 100644 --- a/clippy_lints/src/methods/unwrap_used.rs +++ b/clippy_lints/src/methods/unwrap_used.rs @@ -1,20 +1,20 @@ use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::is_in_test_function; use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{is_in_test_function, is_lint_allowed}; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_span::sym; -use super::UNWRAP_USED; +use super::{EXPECT_USED, UNWRAP_USED}; /// lint use of `unwrap()` for `Option`s and `Result`s pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, allow_unwrap_in_tests: bool) { let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs(); let mess = if is_type_diagnostic_item(cx, obj_ty, sym::Option) { - Some((UNWRAP_USED, "an Option", "None")) + Some((UNWRAP_USED, "an Option", "None", "")) } else if is_type_diagnostic_item(cx, obj_ty, sym::Result) { - Some((UNWRAP_USED, "a Result", "Err")) + Some((UNWRAP_USED, "a Result", "Err", "an ")) } else { None }; @@ -23,18 +23,23 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr return; } - if let Some((lint, kind, none_value)) = mess { + if let Some((lint, kind, none_value, none_prefix)) = mess { + let help = if is_lint_allowed(cx, EXPECT_USED, expr.hir_id) { + format!( + "if you don't want to handle the `{none_value}` case gracefully, consider \ + using `expect()` to provide a better panic message" + ) + } else { + format!("if this value is {none_prefix}`{none_value}`, it will panic") + }; + span_lint_and_help( cx, lint, expr.span, - &format!("used `unwrap()` on `{}` value", kind,), + &format!("used `unwrap()` on `{kind}` value"), None, - &format!( - "if you don't want to handle the `{}` case gracefully, consider \ - using `expect()` to provide a better panic message", - none_value, - ), + &help, ); } } diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index 16d65966c..bc304c081 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -1,7 +1,9 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::qualify_min_const_fn::is_min_const_fn; use clippy_utils::ty::has_drop; -use clippy_utils::{fn_has_unsatisfiable_preds, is_entrypoint_fn, meets_msrv, msrvs, trait_ref_of_method}; +use clippy_utils::{ + fn_has_unsatisfiable_preds, is_entrypoint_fn, is_from_proc_macro, meets_msrv, msrvs, trait_ref_of_method, +}; use rustc_hir as hir; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_hir::intravisit::FnKind; @@ -86,10 +88,10 @@ impl MissingConstForFn { impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { fn check_fn( &mut self, - cx: &LateContext<'_>, - kind: FnKind<'_>, + cx: &LateContext<'tcx>, + kind: FnKind<'tcx>, _: &FnDecl<'_>, - _: &Body<'_>, + body: &Body<'tcx>, span: Span, hir_id: HirId, ) { @@ -124,7 +126,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { FnKind::Method(_, sig, ..) => { if trait_ref_of_method(cx, def_id).is_some() || already_const(sig.header) - || method_accepts_dropable(cx, sig.decl.inputs) + || method_accepts_droppable(cx, sig.decl.inputs) { return; } @@ -144,6 +146,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { } } + if is_from_proc_macro(cx, &(&kind, body, hir_id, span)) { + return; + } + let mir = cx.tcx.optimized_mir(def_id); if let Err((span, err)) = is_min_const_fn(cx.tcx, mir, self.msrv) { @@ -159,7 +165,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { /// Returns true if any of the method parameters is a type that implements `Drop`. The method /// can't be made const then, because `drop` can't be const-evaluated. -fn method_accepts_dropable(cx: &LateContext<'_>, param_tys: &[hir::Ty<'_>]) -> bool { +fn method_accepts_droppable(cx: &LateContext<'_>, param_tys: &[hir::Ty<'_>]) -> bool { // If any of the params are droppable, return true param_tys.iter().any(|hir_ty| { let ty_ty = hir_ty_to_ty(cx.tcx, hir_ty); diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 88ba00292..3701fdb4a 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -7,7 +7,8 @@ use clippy_utils::attrs::is_doc_hidden; use clippy_utils::diagnostics::span_lint; -use rustc_ast::ast; +use clippy_utils::is_from_proc_macro; +use rustc_ast::ast::{self, MetaItem, MetaItemKind}; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty::DefIdTree; @@ -57,6 +58,20 @@ impl MissingDoc { *self.doc_hidden_stack.last().expect("empty doc_hidden_stack") } + fn has_include(meta: Option) -> bool { + if_chain! { + if let Some(meta) = meta; + if let MetaItemKind::List(list) = meta.kind; + if let Some(meta) = list.get(0); + if let Some(name) = meta.ident(); + then { + name.name == sym::include + } else { + false + } + } + } + fn check_missing_docs_attrs( &self, cx: &LateContext<'_>, @@ -80,7 +95,9 @@ impl MissingDoc { return; } - let has_doc = attrs.iter().any(|a| a.doc_str().is_some()); + let has_doc = attrs + .iter() + .any(|a| a.doc_str().is_some() || Self::has_include(a.meta())); if !has_doc { span_lint( cx, @@ -141,14 +158,18 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id()); let attrs = cx.tcx.hir().attrs(it.hir_id()); - self.check_missing_docs_attrs(cx, attrs, it.span, article, desc); + if !is_from_proc_macro(cx, it) { + self.check_missing_docs_attrs(cx, attrs, it.span, article, desc); + } } fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx hir::TraitItem<'_>) { let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id()); let attrs = cx.tcx.hir().attrs(trait_item.hir_id()); - self.check_missing_docs_attrs(cx, attrs, trait_item.span, article, desc); + if !is_from_proc_macro(cx, trait_item) { + self.check_missing_docs_attrs(cx, attrs, trait_item.span, article, desc); + } } fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { @@ -163,18 +184,24 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id()); let attrs = cx.tcx.hir().attrs(impl_item.hir_id()); - self.check_missing_docs_attrs(cx, attrs, impl_item.span, article, desc); + if !is_from_proc_macro(cx, impl_item) { + self.check_missing_docs_attrs(cx, attrs, impl_item.span, article, desc); + } } fn check_field_def(&mut self, cx: &LateContext<'tcx>, sf: &'tcx hir::FieldDef<'_>) { if !sf.is_positional() { let attrs = cx.tcx.hir().attrs(sf.hir_id); - self.check_missing_docs_attrs(cx, attrs, sf.span, "a", "struct field"); + if !is_from_proc_macro(cx, sf) { + self.check_missing_docs_attrs(cx, attrs, sf.span, "a", "struct field"); + } } } fn check_variant(&mut self, cx: &LateContext<'tcx>, v: &'tcx hir::Variant<'_>) { let attrs = cx.tcx.hir().attrs(v.id); - self.check_missing_docs_attrs(cx, attrs, v.span, "a", "variant"); + if !is_from_proc_macro(cx, v) { + self.check_missing_docs_attrs(cx, attrs, v.span, "a", "variant"); + } } } diff --git a/clippy_lints/src/partialeq_to_none.rs b/clippy_lints/src/partialeq_to_none.rs new file mode 100644 index 000000000..eee764206 --- /dev/null +++ b/clippy_lints/src/partialeq_to_none.rs @@ -0,0 +1,104 @@ +use clippy_utils::{ + diagnostics::span_lint_and_sugg, is_lang_ctor, peel_hir_expr_refs, peel_ref_operators, sugg, + ty::is_type_diagnostic_item, +}; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; + +declare_clippy_lint! { + /// ### What it does + /// + /// Checks for binary comparisons to a literal `Option::None`. + /// + /// ### Why is this bad? + /// + /// A programmer checking if some `foo` is `None` via a comparison `foo == None` + /// is usually inspired from other programming languages (e.g. `foo is None` + /// in Python). + /// Checking if a value of type `Option` is (not) equal to `None` in that + /// way relies on `T: PartialEq` to do the comparison, which is unneeded. + /// + /// ### Example + /// ```rust + /// fn foo(f: Option) -> &'static str { + /// if f != None { "yay" } else { "nay" } + /// } + /// ``` + /// Use instead: + /// ```rust + /// fn foo(f: Option) -> &'static str { + /// if f.is_some() { "yay" } else { "nay" } + /// } + /// ``` + #[clippy::version = "1.64.0"] + pub PARTIALEQ_TO_NONE, + style, + "Binary comparison to `Option::None` relies on `T: PartialEq`, which is unneeded" +} +declare_lint_pass!(PartialeqToNone => [PARTIALEQ_TO_NONE]); + +impl<'tcx> LateLintPass<'tcx> for PartialeqToNone { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { + // Skip expanded code, as we have no control over it anyway... + if e.span.from_expansion() { + return; + } + + // If the expression is of type `Option` + let is_ty_option = + |expr: &Expr<'_>| is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr).peel_refs(), sym::Option); + + // If the expression is a literal `Option::None` + let is_none_ctor = |expr: &Expr<'_>| { + matches!(&peel_hir_expr_refs(expr).0.kind, + ExprKind::Path(p) if is_lang_ctor(cx, p, LangItem::OptionNone)) + }; + + let mut applicability = Applicability::MachineApplicable; + + if let ExprKind::Binary(op, left_side, right_side) = e.kind { + // All other comparisons (e.g. `>= None`) have special meaning wrt T + let is_eq = match op.node { + BinOpKind::Eq => true, + BinOpKind::Ne => false, + _ => return, + }; + + // We are only interested in comparisons between `Option` and a literal `Option::None` + let scrutinee = match ( + is_none_ctor(left_side) && is_ty_option(right_side), + is_none_ctor(right_side) && is_ty_option(left_side), + ) { + (true, false) => right_side, + (false, true) => left_side, + _ => return, + }; + + // Peel away refs/derefs (as long as we don't cross manual deref impls), as + // autoref/autoderef will take care of those + let sugg = format!( + "{}.{}", + sugg::Sugg::hir_with_applicability(cx, peel_ref_operators(cx, scrutinee), "..", &mut applicability) + .maybe_par(), + if is_eq { "is_none()" } else { "is_some()" } + ); + + span_lint_and_sugg( + cx, + PARTIALEQ_TO_NONE, + e.span, + "binary comparison to literal `Option::None`", + if is_eq { + "use `Option::is_none()` instead" + } else { + "use `Option::is_some()` instead" + }, + sugg, + applicability, + ); + } + } +} diff --git a/clippy_lints/src/path_buf_push_overwrite.rs b/clippy_lints/src/path_buf_push_overwrite.rs index 3f940ce61..bc6a918f7 100644 --- a/clippy_lints/src/path_buf_push_overwrite.rs +++ b/clippy_lints/src/path_buf_push_overwrite.rs @@ -46,11 +46,9 @@ declare_lint_pass!(PathBufPushOverwrite => [PATH_BUF_PUSH_OVERWRITE]); impl<'tcx> LateLintPass<'tcx> for PathBufPushOverwrite { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { - if let ExprKind::MethodCall(path, args, _) = expr.kind; + if let ExprKind::MethodCall(path, [recv, get_index_arg], _) = expr.kind; if path.ident.name == sym!(push); - if args.len() == 2; - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]).peel_refs(), sym::PathBuf); - if let Some(get_index_arg) = args.get(1); + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv).peel_refs(), sym::PathBuf); if let ExprKind::Lit(ref lit) = get_index_arg.kind; if let LitKind::Str(ref path_lit, _) = lit.node; if let pushed_path = Path::new(path_lit.as_str()); diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index fd0a53839..964a057f0 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -86,8 +86,7 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex if_chain! { if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr); if !is_else_clause(cx.tcx, expr); - if let ExprKind::MethodCall(segment, args, _) = &cond.kind; - if let Some(caller) = args.get(0); + if let ExprKind::MethodCall(segment, [caller, ..], _) = &cond.kind; let caller_ty = cx.typeck_results().expr_ty(caller); let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then, r#else); if is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block); diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 547d4da81..fbf842c33 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -385,24 +385,24 @@ fn check_range_zip_with_len(cx: &LateContext<'_>, path: &PathSegment<'_>, args: if path.ident.as_str() == "zip"; if let [iter, zip_arg] = args; // `.iter()` call - if let ExprKind::MethodCall(iter_path, iter_args, _) = iter.kind; + if let ExprKind::MethodCall(iter_path, [iter_caller, ..], _) = iter.kind; if iter_path.ident.name == sym::iter; // range expression in `.zip()` call: `0..x.len()` if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::Range::hir(zip_arg); if is_integer_const(cx, start, 0); // `.len()` call - if let ExprKind::MethodCall(len_path, len_args, _) = end.kind; - if len_path.ident.name == sym::len && len_args.len() == 1; + if let ExprKind::MethodCall(len_path, [len_caller], _) = end.kind; + if len_path.ident.name == sym::len; // `.iter()` and `.len()` called on same `Path` - if let ExprKind::Path(QPath::Resolved(_, iter_path)) = iter_args[0].kind; - if let ExprKind::Path(QPath::Resolved(_, len_path)) = len_args[0].kind; - if SpanlessEq::new(cx).eq_path_segments(&iter_path.segments, &len_path.segments); + if let ExprKind::Path(QPath::Resolved(_, iter_path)) = iter_caller.kind; + if let ExprKind::Path(QPath::Resolved(_, len_path)) = len_caller.kind; + if SpanlessEq::new(cx).eq_path_segments(iter_path.segments, len_path.segments); then { span_lint(cx, RANGE_ZIP_WITH_LEN, span, &format!("it is more idiomatic to use `{}.iter().enumerate()`", - snippet(cx, iter_args[0].span, "_")) + snippet(cx, iter_caller.span, "_")) ); } } diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs index f5a93ceba..74eea6de4 100644 --- a/clippy_lints/src/redundant_closure_call.rs +++ b/clippy_lints/src/redundant_closure_call.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; -use clippy_utils::source::snippet_with_applicability; +use clippy_utils::sugg::Sugg; use if_chain::if_chain; use rustc_ast::ast; use rustc_ast::visit as ast_visit; @@ -69,7 +69,7 @@ impl EarlyLintPass for RedundantClosureCall { if_chain! { if let ast::ExprKind::Call(ref paren, _) = expr.kind; if let ast::ExprKind::Paren(ref closure) = paren.kind; - if let ast::ExprKind::Closure(_, _, _, _, ref decl, ref block, _) = closure.kind; + if let ast::ExprKind::Closure(_, _, ref r#async, _, ref decl, ref block, _) = closure.kind; then { let mut visitor = ReturnVisitor::new(); visitor.visit_expr(block); @@ -81,10 +81,19 @@ impl EarlyLintPass for RedundantClosureCall { "try not to call a closure in the expression where it is declared", |diag| { if decl.inputs.is_empty() { - let mut app = Applicability::MachineApplicable; - let hint = - snippet_with_applicability(cx, block.span, "..", &mut app).into_owned(); - diag.span_suggestion(expr.span, "try doing something like", hint, app); + let app = Applicability::MachineApplicable; + let mut hint = Sugg::ast(cx, block, ".."); + + if r#async.is_async() { + // `async x` is a syntax error, so it becomes `async { x }` + if !matches!(block.kind, ast::ExprKind::Block(_, _)) { + hint = hint.blockify(); + } + + hint = hint.asyncify(); + } + + diag.span_suggestion(expr.span, "try doing something like", hint.to_string(), app); } }, ); diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index f9a9b0691..6bcae0da8 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -57,21 +57,20 @@ declare_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX]); impl<'tcx> LateLintPass<'tcx> for Regex { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { - if let ExprKind::Call(fun, args) = expr.kind; + if let ExprKind::Call(fun, [arg]) = expr.kind; if let ExprKind::Path(ref qpath) = fun.kind; - if args.len() == 1; if let Some(def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id(); then { if match_def_path(cx, def_id, &paths::REGEX_NEW) || match_def_path(cx, def_id, &paths::REGEX_BUILDER_NEW) { - check_regex(cx, &args[0], true); + check_regex(cx, arg, true); } else if match_def_path(cx, def_id, &paths::REGEX_BYTES_NEW) || match_def_path(cx, def_id, &paths::REGEX_BYTES_BUILDER_NEW) { - check_regex(cx, &args[0], false); + check_regex(cx, arg, false); } else if match_def_path(cx, def_id, &paths::REGEX_SET_NEW) { - check_set(cx, &args[0], true); + check_set(cx, arg, true); } else if match_def_path(cx, def_id, &paths::REGEX_BYTES_SET_NEW) { - check_set(cx, &args[0], false); + check_set(cx, arg, false); } } } diff --git a/clippy_lints/src/renamed_lints.rs b/clippy_lints/src/renamed_lints.rs index ba03ef937..6bea6dc07 100644 --- a/clippy_lints/src/renamed_lints.rs +++ b/clippy_lints/src/renamed_lints.rs @@ -2,6 +2,7 @@ #[rustfmt::skip] pub static RENAMED_LINTS: &[(&str, &str)] = &[ + ("clippy::blacklisted_name", "clippy::disallowed_names"), ("clippy::block_in_if_condition_expr", "clippy::blocks_in_if_conditions"), ("clippy::block_in_if_condition_stmt", "clippy::blocks_in_if_conditions"), ("clippy::box_vec", "clippy::box_collection"), @@ -14,6 +15,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[ ("clippy::for_loop_over_result", "clippy::for_loops_over_fallibles"), ("clippy::identity_conversion", "clippy::useless_conversion"), ("clippy::if_let_some_result", "clippy::match_result_ok"), + ("clippy::logic_bug", "clippy::overly_complex_bool_expr"), ("clippy::new_without_default_derive", "clippy::new_without_default"), ("clippy::option_and_then_some", "clippy::bind_instead_of_map"), ("clippy::option_expect_used", "clippy::expect_used"), diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index 2c8aa17e8..b59a25e3a 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -233,15 +233,10 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { /// Returns `true` if give expression is `repeat(0).take(...)` fn is_repeat_take(&self, expr: &Expr<'_>) -> bool { if_chain! { - if let ExprKind::MethodCall(take_path, take_args, _) = expr.kind; + if let ExprKind::MethodCall(take_path, [recv, len_arg, ..], _) = expr.kind; if take_path.ident.name == sym!(take); - // Check that take is applied to `repeat(0)` - if let Some(repeat_expr) = take_args.get(0); - if self.is_repeat_zero(repeat_expr); - - if let Some(len_arg) = take_args.get(1); - + if self.is_repeat_zero(recv); then { // Check that len expression is equals to `with_capacity` expression if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_alloc.len_expr) { diff --git a/clippy_lints/src/stable_sort_primitive.rs b/clippy_lints/src/stable_sort_primitive.rs index a6c685df7..6d54935f8 100644 --- a/clippy_lints/src/stable_sort_primitive.rs +++ b/clippy_lints/src/stable_sort_primitive.rs @@ -97,12 +97,11 @@ struct LintDetection { fn detect_stable_sort_primitive(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { if_chain! { - if let ExprKind::MethodCall(method_name, args, _) = &expr.kind; - if let Some(slice) = &args.get(0); + if let ExprKind::MethodCall(method_name, [slice, args @ ..], _) = &expr.kind; if let Some(method) = SortingKind::from_stable_name(method_name.ident.name.as_str()); if let Some(slice_type) = is_slice_of_primitives(cx, slice); then { - let args_str = args.iter().skip(1).map(|arg| Sugg::hir(cx, arg, "..").to_string()).collect::>().join(", "); + let args_str = args.iter().map(|arg| Sugg::hir(cx, arg, "..").to_string()).collect::>().join(", "); Some(LintDetection { slice_name: Sugg::hir(cx, slice, "..").to_string(), method, method_args: args_str, slice_type }) } else { None diff --git a/clippy_lints/src/unit_types/mod.rs b/clippy_lints/src/unit_types/mod.rs index 6aa86a57c..546242ebd 100644 --- a/clippy_lints/src/unit_types/mod.rs +++ b/clippy_lints/src/unit_types/mod.rs @@ -103,7 +103,7 @@ impl<'tcx> LateLintPass<'tcx> for UnitTypes { let_unit_value::check(cx, local); } - fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { unit_cmp::check(cx, expr); unit_arg::check(cx, expr); } diff --git a/clippy_lints/src/unit_types/unit_arg.rs b/clippy_lints/src/unit_types/unit_arg.rs index 97d92f10e..16da2f11b 100644 --- a/clippy_lints/src/unit_types/unit_arg.rs +++ b/clippy_lints/src/unit_types/unit_arg.rs @@ -1,4 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::is_from_proc_macro; use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; use if_chain::if_chain; use rustc_errors::Applicability; @@ -7,7 +8,7 @@ use rustc_lint::LateContext; use super::{utils, UNIT_ARG}; -pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if expr.span.from_expansion() { return; } @@ -44,7 +45,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { } }) .collect::>(); - if !args_to_recover.is_empty() { + if !args_to_recover.is_empty() && !is_from_proc_macro(cx, expr) { lint_unit_args(cx, expr, &args_to_recover); } }, diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index fe29bf29d..b6738e289 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -59,17 +59,17 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { ExprKind::Ret(Some(e)) | ExprKind::Break(_, Some(e)) => e, _ => return, }; - if let ExprKind::Call(_, args) = e.kind { - self.try_desugar_arm.push(args[0].hir_id); + if let ExprKind::Call(_, [arg, ..]) = e.kind { + self.try_desugar_arm.push(arg.hir_id); } }, - ExprKind::MethodCall(name, .., args, _) => { + ExprKind::MethodCall(name, .., [recv, ..], _) => { if is_trait_method(cx, e, sym::Into) && name.ident.as_str() == "into" { let a = cx.typeck_results().expr_ty(e); - let b = cx.typeck_results().expr_ty(&args[0]); + let b = cx.typeck_results().expr_ty(recv); if same_type_and_consts(a, b) { - let sugg = snippet_with_macro_callsite(cx, args[0].span, "").to_string(); + let sugg = snippet_with_macro_callsite(cx, recv.span, "").to_string(); span_lint_and_sugg( cx, USELESS_CONVERSION, @@ -90,9 +90,9 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { } } let a = cx.typeck_results().expr_ty(e); - let b = cx.typeck_results().expr_ty(&args[0]); + let b = cx.typeck_results().expr_ty(recv); if same_type_and_consts(a, b) { - let sugg = snippet(cx, args[0].span, "").into_owned(); + let sugg = snippet(cx, recv.span, "").into_owned(); span_lint_and_sugg( cx, USELESS_CONVERSION, @@ -107,7 +107,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { if_chain! { if is_trait_method(cx, e, sym::TryInto) && name.ident.name == sym::try_into; let a = cx.typeck_results().expr_ty(e); - let b = cx.typeck_results().expr_ty(&args[0]); + let b = cx.typeck_results().expr_ty(recv); if is_type_diagnostic_item(cx, a, sym::Result); if let ty::Adt(_, substs) = a.kind(); if let Some(a_type) = substs.types().next(); @@ -126,14 +126,13 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { } }, - ExprKind::Call(path, args) => { + ExprKind::Call(path, [arg]) => { if_chain! { - if args.len() == 1; if let ExprKind::Path(ref qpath) = path.kind; if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id(); then { let a = cx.typeck_results().expr_ty(e); - let b = cx.typeck_results().expr_ty(&args[0]); + let b = cx.typeck_results().expr_ty(arg); if_chain! { if match_def_path(cx, def_id, &paths::TRY_FROM); if is_type_diagnostic_item(cx, a, sym::Result); @@ -159,7 +158,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { if same_type_and_consts(a, b); then { - let sugg = Sugg::hir_with_macro_callsite(cx, &args[0], "").maybe_par(); + let sugg = Sugg::hir_with_macro_callsite(cx, arg, "").maybe_par(); let sugg_msg = format!("consider removing `{}()`", snippet(cx, path.span, "From::from")); span_lint_and_sugg( diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 6e033b3be..3faae9ac0 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -30,7 +30,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[ "MinGW", "CamelCase", ]; -const DEFAULT_BLACKLISTED_NAMES: &[&str] = &["foo", "baz", "quux"]; +const DEFAULT_DISALLOWED_NAMES: &[&str] = &["foo", "baz", "quux"]; /// Holds information used by `MISSING_ENFORCED_IMPORT_RENAMES` lint. #[derive(Clone, Debug, Deserialize)] @@ -68,6 +68,7 @@ pub enum DisallowedType { pub struct TryConf { pub conf: Conf, pub errors: Vec>, + pub warnings: Vec>, } impl TryConf { @@ -75,6 +76,7 @@ impl TryConf { Self { conf: Conf::default(), errors: vec![Box::new(error)], + warnings: vec![], } } } @@ -90,14 +92,14 @@ impl fmt::Display for ConfError { impl Error for ConfError {} -fn conf_error(s: String) -> Box { - Box::new(ConfError(s)) +fn conf_error(s: impl Into) -> Box { + Box::new(ConfError(s.into())) } macro_rules! define_Conf { ($( $(#[doc = $doc:literal])+ - $(#[conf_deprecated($dep:literal)])? + $(#[conf_deprecated($dep:literal, $new_conf:ident)])? ($name:ident: $ty:ty = $default:expr), )*) => { /// Clippy lint configuration @@ -137,17 +139,29 @@ macro_rules! define_Conf { fn visit_map(self, mut map: V) -> Result where V: MapAccess<'de> { let mut errors = Vec::new(); + let mut warnings = Vec::new(); $(let mut $name = None;)* // could get `Field` here directly, but get `str` first for diagnostics while let Some(name) = map.next_key::<&str>()? { match Field::deserialize(name.into_deserializer())? { $(Field::$name => { - $(errors.push(conf_error(format!("deprecated field `{}`. {}", name, $dep)));)? + $(warnings.push(conf_error(format!("deprecated field `{}`. {}", name, $dep)));)? match map.next_value() { Err(e) => errors.push(conf_error(e.to_string())), Ok(value) => match $name { Some(_) => errors.push(conf_error(format!("duplicate field `{}`", name))), - None => $name = Some(value), + None => { + $name = Some(value); + // $new_conf is the same as one of the defined `$name`s, so + // this variable is defined in line 2 of this function. + $(match $new_conf { + Some(_) => errors.push(conf_error(concat!( + "duplicate field `", stringify!($new_conf), + "` (provided as `", stringify!($name), "`)" + ))), + None => $new_conf = $name.clone(), + })? + }, } } })* @@ -156,7 +170,7 @@ macro_rules! define_Conf { } } let conf = Conf { $($name: $name.unwrap_or_else(defaults::$name),)* }; - Ok(TryConf { conf, errors }) + Ok(TryConf { conf, errors, warnings }) } } @@ -203,12 +217,11 @@ define_Conf! { /// /// The minimum rust version that the project supports (msrv: Option = None), - /// Lint: BLACKLISTED_NAME. + /// DEPRECATED LINT: BLACKLISTED_NAME. /// - /// The list of blacklisted names to lint about. NB: `bar` is not here since it has legitimate uses. The value - /// `".."` can be used as part of the list to indicate, that the configured values should be appended to the - /// default configuration of Clippy. By default any configuraction will replace the default value. - (blacklisted_names: Vec = super::DEFAULT_BLACKLISTED_NAMES.iter().map(ToString::to_string).collect()), + /// Use the Disallowed Names lint instead + #[conf_deprecated("Please use `disallowed-names` instead", disallowed_names)] + (blacklisted_names: Vec = Vec::new()), /// Lint: COGNITIVE_COMPLEXITY. /// /// The maximum cognitive complexity a function can have @@ -216,8 +229,14 @@ define_Conf! { /// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY. /// /// Use the Cognitive Complexity lint instead. - #[conf_deprecated("Please use `cognitive-complexity-threshold` instead")] - (cyclomatic_complexity_threshold: Option = None), + #[conf_deprecated("Please use `cognitive-complexity-threshold` instead", cognitive_complexity_threshold)] + (cyclomatic_complexity_threshold: u64 = 25), + /// Lint: DISALLOWED_NAMES. + /// + /// The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value + /// `".."` can be used as part of the list to indicate, that the configured values should be appended to the + /// default configuration of Clippy. By default any configuration will replace the default value. + (disallowed_names: Vec = super::DEFAULT_DISALLOWED_NAMES.iter().map(ToString::to_string).collect()), /// Lint: DOC_MARKDOWN. /// /// The list of words this lint should not consider as identifiers needing ticks. The value @@ -420,7 +439,7 @@ pub fn read(path: &Path) -> TryConf { match toml::from_str::(&content) { Ok(mut conf) => { extend_vec_if_indicator_present(&mut conf.conf.doc_valid_idents, DEFAULT_DOC_VALID_IDENTS); - extend_vec_if_indicator_present(&mut conf.conf.blacklisted_names, DEFAULT_BLACKLISTED_NAMES); + extend_vec_if_indicator_present(&mut conf.conf.disallowed_names, DEFAULT_DISALLOWED_NAMES); conf }, diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index b30965329..5dcacd604 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -496,12 +496,14 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { cx, }; let body_id = cx.tcx.hir().body_owned_by( - impl_item_refs - .iter() - .find(|iiref| iiref.ident.as_str() == "get_lints") - .expect("LintPass needs to implement get_lints") - .id - .hir_id(), + cx.tcx.hir().local_def_id( + impl_item_refs + .iter() + .find(|iiref| iiref.ident.as_str() == "get_lints") + .expect("LintPass needs to implement get_lints") + .id + .hir_id(), + ), ); collector.visit_expr(&cx.tcx.hir().body(body_id).value); } @@ -569,7 +571,7 @@ fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<' item.span, "this item has an invalid `clippy::version` attribute", None, - "please use a valid sematic version, see `doc/adding_lints.md`", + "please use a valid semantic version, see `doc/adding_lints.md`", ); } } else { diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs index 92934c16d..92cf42c7a 100644 --- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -619,7 +619,7 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector { if_chain! { // item validation if is_lint_ref_type(cx, ty); - // blacklist check + // disallow check let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase(); if !BLACK_LISTED_LINTS.contains(&lint_name.as_str()); // metadata extraction @@ -644,7 +644,7 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector { if_chain! { if is_deprecated_lint(cx, ty); - // blacklist check + // disallow check let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase(); if !BLACK_LISTED_LINTS.contains(&lint_name.as_str()); // Metadata the little we can get from a deprecated lint diff --git a/clippy_lints/src/verbose_file_reads.rs b/clippy_lints/src/verbose_file_reads.rs index 8e2ddd225..afd0077a6 100644 --- a/clippy_lints/src/verbose_file_reads.rs +++ b/clippy_lints/src/verbose_file_reads.rs @@ -61,10 +61,10 @@ impl<'tcx> LateLintPass<'tcx> for VerboseFileReads { fn is_file_read_to_end<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { if_chain! { - if let ExprKind::MethodCall(method_name, exprs, _) = expr.kind; + if let ExprKind::MethodCall(method_name, [recv, ..], _) = expr.kind; if method_name.ident.as_str() == "read_to_end"; - if let ExprKind::Path(QPath::Resolved(None, _)) = &exprs[0].kind; - let ty = cx.typeck_results().expr_ty(&exprs[0]); + if let ExprKind::Path(QPath::Resolved(None, _)) = &recv.kind; + let ty = cx.typeck_results().expr_ty(recv); if match_type(cx, ty, &paths::FILE); then { return true diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml index bb443bdc1..a688050f6 100644 --- a/clippy_utils/Cargo.toml +++ b/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.64" +version = "0.1.65" edition = "2021" publish = false diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs new file mode 100644 index 000000000..8335ffae8 --- /dev/null +++ b/clippy_utils/src/check_proc_macro.rs @@ -0,0 +1,329 @@ +//! This module handles checking if the span given is from a proc-macro or not. +//! +//! Proc-macros are capable of setting the span of every token they output to a few possible spans. +//! This includes spans we can detect easily as coming from a proc-macro (e.g. the call site +//! or the def site), and spans we can't easily detect as such (e.g. the span of any token +//! passed into the proc macro). This capability means proc-macros are capable of generating code +//! with a span that looks like it was written by the user, but which should not be linted by clippy +//! as it was generated by an external macro. +//! +//! That brings us to this module. The current approach is to determine a small bit of text which +//! must exist at both the start and the end of an item (e.g. an expression or a path) assuming the +//! code was written, and check if the span contains that text. Note this will only work correctly +//! if the span is not from a `macro_rules` based macro. + +use rustc_ast::ast::{IntTy, LitIntType, LitKind, StrStyle, UintTy}; +use rustc_hir::{ + intravisit::FnKind, Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, HirId, + Impl, ImplItem, ImplItemKind, IsAuto, Item, ItemKind, LoopSource, MatchSource, Node, QPath, TraitItem, + TraitItemKind, UnOp, UnsafeSource, Unsafety, Variant, VariantData, YieldSource, +}; +use rustc_lint::{LateContext, LintContext}; +use rustc_middle::ty::TyCtxt; +use rustc_session::Session; +use rustc_span::{Span, Symbol}; +use rustc_target::spec::abi::Abi; + +/// The search pattern to look for. Used by `span_matches_pat` +#[derive(Clone, Copy)] +pub enum Pat { + /// A single string. + Str(&'static str), + /// Any of the given strings. + MultiStr(&'static [&'static str]), + /// The string representation of the symbol. + Sym(Symbol), + /// Any decimal or hexadecimal digit depending on the location. + Num, +} + +/// Checks if the start and the end of the span's text matches the patterns. This will return false +/// if the span crosses multiple files or if source is not available. +fn span_matches_pat(sess: &Session, span: Span, start_pat: Pat, end_pat: Pat) -> bool { + let pos = sess.source_map().lookup_byte_offset(span.lo()); + let Some(ref src) = pos.sf.src else { + return false; + }; + let end = span.hi() - pos.sf.start_pos; + src.get(pos.pos.0 as usize..end.0 as usize).map_or(false, |s| { + // Spans can be wrapped in a mixture or parenthesis, whitespace, and trailing commas. + let start_str = s.trim_start_matches(|c: char| c.is_whitespace() || c == '('); + let end_str = s.trim_end_matches(|c: char| c.is_whitespace() || c == ')' || c == ','); + (match start_pat { + Pat::Str(text) => start_str.starts_with(text), + Pat::MultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)), + Pat::Sym(sym) => start_str.starts_with(sym.as_str()), + Pat::Num => start_str.as_bytes().first().map_or(false, u8::is_ascii_digit), + } && match end_pat { + Pat::Str(text) => end_str.ends_with(text), + Pat::MultiStr(texts) => texts.iter().any(|s| start_str.ends_with(s)), + Pat::Sym(sym) => end_str.ends_with(sym.as_str()), + Pat::Num => end_str.as_bytes().last().map_or(false, u8::is_ascii_hexdigit), + }) + }) +} + +/// Get the search patterns to use for the given literal +fn lit_search_pat(lit: &LitKind) -> (Pat, Pat) { + match lit { + LitKind::Str(_, StrStyle::Cooked) => (Pat::Str("\""), Pat::Str("\"")), + LitKind::Str(_, StrStyle::Raw(0)) => (Pat::Str("r"), Pat::Str("\"")), + LitKind::Str(_, StrStyle::Raw(_)) => (Pat::Str("r#"), Pat::Str("#")), + LitKind::ByteStr(_) => (Pat::Str("b\""), Pat::Str("\"")), + LitKind::Byte(_) => (Pat::Str("b'"), Pat::Str("'")), + LitKind::Char(_) => (Pat::Str("'"), Pat::Str("'")), + LitKind::Int(_, LitIntType::Signed(IntTy::Isize)) => (Pat::Num, Pat::Str("isize")), + LitKind::Int(_, LitIntType::Unsigned(UintTy::Usize)) => (Pat::Num, Pat::Str("usize")), + LitKind::Int(..) => (Pat::Num, Pat::Num), + LitKind::Float(..) => (Pat::Num, Pat::Str("")), + LitKind::Bool(true) => (Pat::Str("true"), Pat::Str("true")), + LitKind::Bool(false) => (Pat::Str("false"), Pat::Str("false")), + _ => (Pat::Str(""), Pat::Str("")), + } +} + +/// Get the search patterns to use for the given path +fn qpath_search_pat(path: &QPath<'_>) -> (Pat, Pat) { + match path { + QPath::Resolved(ty, path) => { + let start = if ty.is_some() { + Pat::Str("<") + } else { + path.segments + .first() + .map_or(Pat::Str(""), |seg| Pat::Sym(seg.ident.name)) + }; + let end = path.segments.last().map_or(Pat::Str(""), |seg| { + if seg.args.is_some() { + Pat::Str(">") + } else { + Pat::Sym(seg.ident.name) + } + }); + (start, end) + }, + QPath::TypeRelative(_, name) => (Pat::Str(""), Pat::Sym(name.ident.name)), + QPath::LangItem(..) => (Pat::Str(""), Pat::Str("")), + } +} + +/// Get the search patterns to use for the given expression +fn expr_search_pat(tcx: TyCtxt<'_>, e: &Expr<'_>) -> (Pat, Pat) { + match e.kind { + ExprKind::Box(e) => (Pat::Str("box"), expr_search_pat(tcx, e).1), + ExprKind::ConstBlock(_) => (Pat::Str("const"), Pat::Str("}")), + ExprKind::Tup([]) => (Pat::Str(")"), Pat::Str("(")), + ExprKind::Unary(UnOp::Deref, e) => (Pat::Str("*"), expr_search_pat(tcx, e).1), + ExprKind::Unary(UnOp::Not, e) => (Pat::Str("!"), expr_search_pat(tcx, e).1), + ExprKind::Unary(UnOp::Neg, e) => (Pat::Str("-"), expr_search_pat(tcx, e).1), + ExprKind::Lit(ref lit) => lit_search_pat(&lit.node), + ExprKind::Array(_) | ExprKind::Repeat(..) => (Pat::Str("["), Pat::Str("]")), + ExprKind::Call(e, []) | ExprKind::MethodCall(_, [e], _) => (expr_search_pat(tcx, e).0, Pat::Str("(")), + ExprKind::Call(first, [.., last]) + | ExprKind::MethodCall(_, [first, .., last], _) + | ExprKind::Binary(_, first, last) + | ExprKind::Tup([first, .., last]) + | ExprKind::Assign(first, last, _) + | ExprKind::AssignOp(_, first, last) => (expr_search_pat(tcx, first).0, expr_search_pat(tcx, last).1), + ExprKind::Tup([e]) | ExprKind::DropTemps(e) => expr_search_pat(tcx, e), + ExprKind::Cast(e, _) | ExprKind::Type(e, _) => (expr_search_pat(tcx, e).0, Pat::Str("")), + ExprKind::Let(let_expr) => (Pat::Str("let"), expr_search_pat(tcx, let_expr.init).1), + ExprKind::If(..) => (Pat::Str("if"), Pat::Str("}")), + ExprKind::Loop(_, Some(_), _, _) | ExprKind::Block(_, Some(_)) => (Pat::Str("'"), Pat::Str("}")), + ExprKind::Loop(_, None, LoopSource::Loop, _) => (Pat::Str("loop"), Pat::Str("}")), + ExprKind::Loop(_, None, LoopSource::While, _) => (Pat::Str("while"), Pat::Str("}")), + ExprKind::Loop(_, None, LoopSource::ForLoop, _) | ExprKind::Match(_, _, MatchSource::ForLoopDesugar) => { + (Pat::Str("for"), Pat::Str("}")) + }, + ExprKind::Match(_, _, MatchSource::Normal) => (Pat::Str("match"), Pat::Str("}")), + ExprKind::Match(e, _, MatchSource::TryDesugar) => (expr_search_pat(tcx, e).0, Pat::Str("?")), + ExprKind::Match(e, _, MatchSource::AwaitDesugar) | ExprKind::Yield(e, YieldSource::Await { .. }) => { + (expr_search_pat(tcx, e).0, Pat::Str("await")) + }, + ExprKind::Closure(&Closure { body, .. }) => (Pat::Str(""), expr_search_pat(tcx, &tcx.hir().body(body).value).1), + ExprKind::Block( + Block { + rules: BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided), + .. + }, + None, + ) => (Pat::Str("unsafe"), Pat::Str("}")), + ExprKind::Block(_, None) => (Pat::Str("{"), Pat::Str("}")), + ExprKind::Field(e, name) => (expr_search_pat(tcx, e).0, Pat::Sym(name.name)), + ExprKind::Index(e, _) => (expr_search_pat(tcx, e).0, Pat::Str("]")), + ExprKind::Path(ref path) => qpath_search_pat(path), + ExprKind::AddrOf(_, _, e) => (Pat::Str("&"), expr_search_pat(tcx, e).1), + ExprKind::Break(Destination { label: None, .. }, None) => (Pat::Str("break"), Pat::Str("break")), + ExprKind::Break(Destination { label: Some(name), .. }, None) => (Pat::Str("break"), Pat::Sym(name.ident.name)), + ExprKind::Break(_, Some(e)) => (Pat::Str("break"), expr_search_pat(tcx, e).1), + ExprKind::Continue(Destination { label: None, .. }) => (Pat::Str("continue"), Pat::Str("continue")), + ExprKind::Continue(Destination { label: Some(name), .. }) => (Pat::Str("continue"), Pat::Sym(name.ident.name)), + ExprKind::Ret(None) => (Pat::Str("return"), Pat::Str("return")), + ExprKind::Ret(Some(e)) => (Pat::Str("return"), expr_search_pat(tcx, e).1), + ExprKind::Struct(path, _, _) => (qpath_search_pat(path).0, Pat::Str("}")), + ExprKind::Yield(e, YieldSource::Yield) => (Pat::Str("yield"), expr_search_pat(tcx, e).1), + _ => (Pat::Str(""), Pat::Str("")), + } +} + +fn fn_header_search_pat(header: FnHeader) -> Pat { + if header.is_async() { + Pat::Str("async") + } else if header.is_const() { + Pat::Str("const") + } else if header.is_unsafe() { + Pat::Str("unsafe") + } else if header.abi != Abi::Rust { + Pat::Str("extern") + } else { + Pat::MultiStr(&["fn", "extern"]) + } +} + +fn item_search_pat(item: &Item<'_>) -> (Pat, Pat) { + let (start_pat, end_pat) = match &item.kind { + ItemKind::ExternCrate(_) => (Pat::Str("extern"), Pat::Str(";")), + ItemKind::Static(..) => (Pat::Str("static"), Pat::Str(";")), + ItemKind::Const(..) => (Pat::Str("const"), Pat::Str(";")), + ItemKind::Fn(sig, ..) => (fn_header_search_pat(sig.header), Pat::Str("")), + ItemKind::ForeignMod { .. } => (Pat::Str("extern"), Pat::Str("}")), + ItemKind::TyAlias(..) | ItemKind::OpaqueTy(_) => (Pat::Str("type"), Pat::Str(";")), + ItemKind::Enum(..) => (Pat::Str("enum"), Pat::Str("}")), + ItemKind::Struct(VariantData::Struct(..), _) => (Pat::Str("struct"), Pat::Str("}")), + ItemKind::Struct(..) => (Pat::Str("struct"), Pat::Str(";")), + ItemKind::Union(..) => (Pat::Str("union"), Pat::Str("}")), + ItemKind::Trait(_, Unsafety::Unsafe, ..) + | ItemKind::Impl(Impl { + unsafety: Unsafety::Unsafe, + .. + }) => (Pat::Str("unsafe"), Pat::Str("}")), + ItemKind::Trait(IsAuto::Yes, ..) => (Pat::Str("auto"), Pat::Str("}")), + ItemKind::Trait(..) => (Pat::Str("trait"), Pat::Str("}")), + ItemKind::Impl(_) => (Pat::Str("impl"), Pat::Str("}")), + _ => return (Pat::Str(""), Pat::Str("")), + }; + if item.vis_span.is_empty() { + (start_pat, end_pat) + } else { + (Pat::Str("pub"), end_pat) + } +} + +fn trait_item_search_pat(item: &TraitItem<'_>) -> (Pat, Pat) { + match &item.kind { + TraitItemKind::Const(..) => (Pat::Str("const"), Pat::Str(";")), + TraitItemKind::Type(..) => (Pat::Str("type"), Pat::Str(";")), + TraitItemKind::Fn(sig, ..) => (fn_header_search_pat(sig.header), Pat::Str("")), + } +} + +fn impl_item_search_pat(item: &ImplItem<'_>) -> (Pat, Pat) { + let (start_pat, end_pat) = match &item.kind { + ImplItemKind::Const(..) => (Pat::Str("const"), Pat::Str(";")), + ImplItemKind::TyAlias(..) => (Pat::Str("type"), Pat::Str(";")), + ImplItemKind::Fn(sig, ..) => (fn_header_search_pat(sig.header), Pat::Str("")), + }; + if item.vis_span.is_empty() { + (start_pat, end_pat) + } else { + (Pat::Str("pub"), end_pat) + } +} + +fn field_def_search_pat(def: &FieldDef<'_>) -> (Pat, Pat) { + if def.vis_span.is_empty() { + if def.is_positional() { + (Pat::Str(""), Pat::Str("")) + } else { + (Pat::Sym(def.ident.name), Pat::Str("")) + } + } else { + (Pat::Str("pub"), Pat::Str("")) + } +} + +fn variant_search_pat(v: &Variant<'_>) -> (Pat, Pat) { + match v.data { + VariantData::Struct(..) => (Pat::Sym(v.ident.name), Pat::Str("}")), + VariantData::Tuple(..) => (Pat::Sym(v.ident.name), Pat::Str("")), + VariantData::Unit(..) => (Pat::Sym(v.ident.name), Pat::Sym(v.ident.name)), + } +} + +fn fn_kind_pat(tcx: TyCtxt<'_>, kind: &FnKind<'_>, body: &Body<'_>, hir_id: HirId) -> (Pat, Pat) { + let (start_pat, end_pat) = match kind { + FnKind::ItemFn(.., header) => (fn_header_search_pat(*header), Pat::Str("")), + FnKind::Method(.., sig) => (fn_header_search_pat(sig.header), Pat::Str("")), + FnKind::Closure => return (Pat::Str(""), expr_search_pat(tcx, &body.value).1), + }; + let start_pat = match tcx.hir().get(hir_id) { + Node::Item(Item { vis_span, .. }) | Node::ImplItem(ImplItem { vis_span, .. }) => { + if vis_span.is_empty() { + start_pat + } else { + Pat::Str("pub") + } + }, + Node::TraitItem(_) => start_pat, + _ => Pat::Str(""), + }; + (start_pat, end_pat) +} + +pub trait WithSearchPat { + type Context: LintContext; + fn search_pat(&self, cx: &Self::Context) -> (Pat, Pat); + fn span(&self) -> Span; +} +macro_rules! impl_with_search_pat { + ($cx:ident: $ty:ident with $fn:ident $(($tcx:ident))?) => { + impl<'cx> WithSearchPat for $ty<'cx> { + type Context = $cx<'cx>; + #[allow(unused_variables)] + fn search_pat(&self, cx: &Self::Context) -> (Pat, Pat) { + $(let $tcx = cx.tcx;)? + $fn($($tcx,)? self) + } + fn span(&self) -> Span { + self.span + } + } + }; +} +impl_with_search_pat!(LateContext: Expr with expr_search_pat(tcx)); +impl_with_search_pat!(LateContext: Item with item_search_pat); +impl_with_search_pat!(LateContext: TraitItem with trait_item_search_pat); +impl_with_search_pat!(LateContext: ImplItem with impl_item_search_pat); +impl_with_search_pat!(LateContext: FieldDef with field_def_search_pat); +impl_with_search_pat!(LateContext: Variant with variant_search_pat); + +impl<'cx> WithSearchPat for (&FnKind<'cx>, &Body<'cx>, HirId, Span) { + type Context = LateContext<'cx>; + + fn search_pat(&self, cx: &Self::Context) -> (Pat, Pat) { + fn_kind_pat(cx.tcx, self.0, self.1, self.2) + } + + fn span(&self) -> Span { + self.3 + } +} + +/// Checks if the item likely came from a proc-macro. +/// +/// This should be called after `in_external_macro` and the initial pattern matching of the ast as +/// it is significantly slower than both of those. +pub fn is_from_proc_macro(cx: &T::Context, item: &T) -> bool { + let (start_pat, end_pat) = item.search_pat(cx); + !span_matches_pat(cx.sess(), item.span(), start_pat, end_pat) +} + +/// Checks if the span actually refers to a match expression +pub fn is_span_match(cx: &impl LintContext, span: Span) -> bool { + span_matches_pat(cx.sess(), span, Pat::Str("match"), Pat::Str("}")) +} + +/// Checks if the span actually refers to an if expression +pub fn is_span_if(cx: &impl LintContext, span: Span) -> bool { + span_matches_pat(cx.sess(), span, Pat::Str("if"), Pat::Str("}")) +} diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 7493a8685..2616a578b 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -39,6 +39,7 @@ pub mod sym_helper; pub mod ast_utils; pub mod attrs; +mod check_proc_macro; pub mod comparisons; pub mod consts; pub mod diagnostics; @@ -59,6 +60,7 @@ pub mod usage; pub mod visitors; pub use self::attrs::*; +pub use self::check_proc_macro::{is_from_proc_macro, is_span_if, is_span_match}; pub use self::hir_utils::{ both, count_eq, eq_expr_value, hash_expr, hash_stmt, over, HirEqInterExpr, SpanlessEq, SpanlessHash, }; diff --git a/clippy_utils/src/numeric_literal.rs b/clippy_utils/src/numeric_literal.rs index 3fb5415ce..80098d976 100644 --- a/clippy_utils/src/numeric_literal.rs +++ b/clippy_utils/src/numeric_literal.rs @@ -223,10 +223,12 @@ impl<'a> NumericLiteral<'a> { fn split_suffix<'a>(src: &'a str, lit_kind: &LitKind) -> (&'a str, Option<&'a str>) { debug_assert!(lit_kind.is_numeric()); - lit_suffix_length(lit_kind).map_or((src, None), |suffix_length| { - let (unsuffixed, suffix) = src.split_at(src.len() - suffix_length); - (unsuffixed, Some(suffix)) - }) + lit_suffix_length(lit_kind) + .and_then(|suffix_length| src.len().checked_sub(suffix_length)) + .map_or((src, None), |split_pos| { + let (unsuffixed, suffix) = src.split_at(split_pos); + (unsuffixed, Some(suffix)) + }) } fn lit_suffix_length(lit_kind: &LitKind) -> Option { diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index 05429d05d..8d697a301 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -194,3 +194,5 @@ pub const VEC_RESIZE: [&str; 4] = ["alloc", "vec", "Vec", "resize"]; pub const WEAK_ARC: [&str; 3] = ["alloc", "sync", "Weak"]; pub const WEAK_RC: [&str; 3] = ["alloc", "rc", "Weak"]; pub const PTR_NON_NULL: [&str; 4] = ["core", "ptr", "non_null", "NonNull"]; +pub const INSTANT_NOW: [&str; 4] = ["std", "time", "Instant", "now"]; +pub const INSTANT: [&str; 3] = ["std", "time", "Instant"]; diff --git a/clippy_utils/src/source.rs b/clippy_utils/src/source.rs index 1197fe914..d85f591fb 100644 --- a/clippy_utils/src/source.rs +++ b/clippy_utils/src/source.rs @@ -11,24 +11,6 @@ use rustc_span::source_map::SourceMap; use rustc_span::{BytePos, Pos, Span, SpanData, SyntaxContext}; use std::borrow::Cow; -/// Checks if the span starts with the given text. This will return false if the span crosses -/// multiple files or if source is not available. -/// -/// This is used to check for proc macros giving unhelpful spans to things. -pub fn span_starts_with(cx: &T, span: Span, text: &str) -> bool { - fn helper(sm: &SourceMap, span: Span, text: &str) -> bool { - let pos = sm.lookup_byte_offset(span.lo()); - let Some(ref src) = pos.sf.src else { - return false; - }; - let end = span.hi() - pos.sf.start_pos; - src.get(pos.pos.0 as usize..end.0 as usize) - // Expression spans can include wrapping parenthesis. Remove them first. - .map_or(false, |s| s.trim_start_matches('(').starts_with(text)) - } - helper(cx.sess().source_map(), span, text) -} - /// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`. /// Also takes an `Option` which can be put inside the braces. pub fn expr_block<'a, T: LintContext>( diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index bad291dfc..081c98e2f 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -315,6 +315,12 @@ impl<'a> Sugg<'a> { Sugg::NonParen(Cow::Owned(format!("{{ {} }}", self))) } + /// Convenience method to prefix the expression with the `async` keyword. + /// Can be used after `blockify` to create an async block. + pub fn asyncify(self) -> Sugg<'static> { + Sugg::NonParen(Cow::Owned(format!("async {}", self))) + } + /// Convenience method to create the `..` or `...` /// suggestion. pub fn range(self, end: &Self, limit: ast::RangeLimits) -> Sugg<'static> { diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index a05d633d9..e7d670766 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -503,7 +503,7 @@ pub fn all_predicates_of(tcx: TyCtxt<'_>, id: DefId) -> impl Iterator { Sig(Binder<'tcx, FnSig<'tcx>>, Option), Closure(Option<&'tcx FnDecl<'tcx>>, Binder<'tcx, FnSig<'tcx>>), - Trait(Binder<'tcx, Ty<'tcx>>, Option>>), + Trait(Binder<'tcx, Ty<'tcx>>, Option>>, Option), } impl<'tcx> ExprFnSig<'tcx> { /// Gets the argument type at the given offset. This will return `None` when the index is out of @@ -518,7 +518,7 @@ impl<'tcx> ExprFnSig<'tcx> { } }, Self::Closure(_, sig) => Some(sig.input(0).map_bound(|ty| ty.tuple_fields()[i])), - Self::Trait(inputs, _) => Some(inputs.map_bound(|ty| ty.tuple_fields()[i])), + Self::Trait(inputs, _, _) => Some(inputs.map_bound(|ty| ty.tuple_fields()[i])), } } @@ -541,7 +541,7 @@ impl<'tcx> ExprFnSig<'tcx> { decl.and_then(|decl| decl.inputs.get(i)), sig.input(0).map_bound(|ty| ty.tuple_fields()[i]), )), - Self::Trait(inputs, _) => Some((None, inputs.map_bound(|ty| ty.tuple_fields()[i]))), + Self::Trait(inputs, _, _) => Some((None, inputs.map_bound(|ty| ty.tuple_fields()[i]))), } } @@ -550,12 +550,16 @@ impl<'tcx> ExprFnSig<'tcx> { pub fn output(self) -> Option>> { match self { Self::Sig(sig, _) | Self::Closure(_, sig) => Some(sig.output()), - Self::Trait(_, output) => output, + Self::Trait(_, output, _) => output, } } pub fn predicates_id(&self) -> Option { - if let ExprFnSig::Sig(_, id) = *self { id } else { None } + if let ExprFnSig::Sig(_, id) | ExprFnSig::Trait(_, _, id) = *self { + id + } else { + None + } } } @@ -568,7 +572,8 @@ pub fn expr_sig<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option> { +/// If the type is function like, get the signature for it. +pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option> { if ty.is_box() { return ty_sig(cx, ty.boxed_ty()); } @@ -580,7 +585,7 @@ fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option> Some(ExprFnSig::Closure(decl, subs.as_closure().sig())) }, ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.bound_fn_sig(id).subst(cx.tcx, subs), Some(id))), - ty::Opaque(id, _) => ty_sig(cx, cx.tcx.type_of(id)), + ty::Opaque(id, _) => sig_from_bounds(cx, ty, cx.tcx.item_bounds(id), cx.tcx.opt_parent(id)), ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)), ty::Dynamic(bounds, _) => { let lang_items = cx.tcx.lang_items(); @@ -594,26 +599,31 @@ fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option> .projection_bounds() .find(|p| lang_items.fn_once_output().map_or(false, |id| id == p.item_def_id())) .map(|p| p.map_bound(|p| p.term.ty().unwrap())); - Some(ExprFnSig::Trait(bound.map_bound(|b| b.substs.type_at(0)), output)) + Some(ExprFnSig::Trait(bound.map_bound(|b| b.substs.type_at(0)), output, None)) }, _ => None, } }, ty::Projection(proj) => match cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) { Ok(normalized_ty) if normalized_ty != ty => ty_sig(cx, normalized_ty), - _ => sig_for_projection(cx, proj).or_else(|| sig_from_bounds(cx, ty)), + _ => sig_for_projection(cx, proj).or_else(|| sig_from_bounds(cx, ty, cx.param_env.caller_bounds(), None)), }, - ty::Param(_) => sig_from_bounds(cx, ty), + ty::Param(_) => sig_from_bounds(cx, ty, cx.param_env.caller_bounds(), None), _ => None, } } -fn sig_from_bounds<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option> { +fn sig_from_bounds<'tcx>( + cx: &LateContext<'tcx>, + ty: Ty<'tcx>, + predicates: &'tcx [Predicate<'tcx>], + predicates_id: Option, +) -> Option> { let mut inputs = None; let mut output = None; let lang_items = cx.tcx.lang_items(); - for (pred, _) in all_predicates_of(cx.tcx, cx.typeck_results().hir_owner.to_def_id()) { + for pred in predicates { match pred.kind().skip_binder() { PredicateKind::Trait(p) if (lang_items.fn_trait() == Some(p.def_id()) @@ -621,11 +631,12 @@ fn sig_from_bounds<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option { - if inputs.is_some() { + let i = pred.kind().rebind(p.trait_ref.substs.type_at(1)); + if inputs.map_or(false, |inputs| i != inputs) { // Multiple different fn trait impls. Is this even allowed? return None; } - inputs = Some(pred.kind().rebind(p.trait_ref.substs.type_at(1))); + inputs = Some(i); }, PredicateKind::Projection(p) if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output() @@ -641,7 +652,7 @@ fn sig_from_bounds<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> Option> { @@ -661,14 +672,15 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> O || lang_items.fn_mut_trait() == Some(p.def_id()) || lang_items.fn_once_trait() == Some(p.def_id())) => { - if inputs.is_some() { + let i = pred + .map_bound(|pred| pred.kind().rebind(p.trait_ref.substs.type_at(1))) + .subst(cx.tcx, ty.substs); + + if inputs.map_or(false, |inputs| inputs != i) { // Multiple different fn trait impls. Is this even allowed? return None; } - inputs = Some( - pred.map_bound(|pred| pred.kind().rebind(p.trait_ref.substs.type_at(1))) - .subst(cx.tcx, ty.substs), - ); + inputs = Some(i); }, PredicateKind::Projection(p) if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output() => { if output.is_some() { @@ -684,7 +696,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> O } } - inputs.map(|ty| ExprFnSig::Trait(ty, output)) + inputs.map(|ty| ExprFnSig::Trait(ty, output, None)) } #[derive(Clone, Copy)] diff --git a/rust-toolchain b/rust-toolchain index 23ba7c712..7e14df4fe 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2022-07-28" +channel = "nightly-2022-08-11" components = ["cargo", "llvm-tools-preview", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] diff --git a/tests/ui-internal/check_clippy_version_attribute.stderr b/tests/ui-internal/check_clippy_version_attribute.stderr index 533107588..2aa4de490 100644 --- a/tests/ui-internal/check_clippy_version_attribute.stderr +++ b/tests/ui-internal/check_clippy_version_attribute.stderr @@ -16,7 +16,7 @@ note: the lint level is defined here LL | #![deny(clippy::internal)] | ^^^^^^^^^^^^^^^^ = note: `#[deny(clippy::invalid_clippy_version_attribute)]` implied by `#[deny(clippy::internal)]` - = help: please use a valid sematic version, see `doc/adding_lints.md` + = help: please use a valid semantic version, see `doc/adding_lints.md` = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info) error: this item has an invalid `clippy::version` attribute @@ -31,7 +31,7 @@ LL | | report_in_external_macro: true LL | | } | |_^ | - = help: please use a valid sematic version, see `doc/adding_lints.md` + = help: please use a valid semantic version, see `doc/adding_lints.md` = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info) error: this lint is missing the `clippy::version` attribute or version value diff --git a/tests/ui-toml/bad_toml_type/clippy.toml b/tests/ui-toml/bad_toml_type/clippy.toml index 168675394..d48bab08f 100644 --- a/tests/ui-toml/bad_toml_type/clippy.toml +++ b/tests/ui-toml/bad_toml_type/clippy.toml @@ -1 +1 @@ -blacklisted-names = 42 +disallowed-names = 42 diff --git a/tests/ui-toml/bad_toml_type/conf_bad_type.stderr b/tests/ui-toml/bad_toml_type/conf_bad_type.stderr index c7bc261de..e3ec60192 100644 --- a/tests/ui-toml/bad_toml_type/conf_bad_type.stderr +++ b/tests/ui-toml/bad_toml_type/conf_bad_type.stderr @@ -1,4 +1,4 @@ -error: error reading Clippy's configuration file `$DIR/clippy.toml`: invalid type: integer `42`, expected a sequence for key `blacklisted-names` +error: error reading Clippy's configuration file `$DIR/clippy.toml`: invalid type: integer `42`, expected a sequence for key `disallowed-names` error: aborting due to previous error diff --git a/tests/ui-toml/blacklisted_names_append/blacklisted_names.stderr b/tests/ui-toml/blacklisted_names_append/blacklisted_names.stderr deleted file mode 100644 index 9169bb0e8..000000000 --- a/tests/ui-toml/blacklisted_names_append/blacklisted_names.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: use of a blacklisted/placeholder name `foo` - --> $DIR/blacklisted_names.rs:5:9 - | -LL | let foo = "bar"; - | ^^^ - | - = note: `-D clippy::blacklisted-name` implied by `-D warnings` - -error: use of a blacklisted/placeholder name `ducks` - --> $DIR/blacklisted_names.rs:7:9 - | -LL | let ducks = ["quack", "quack"]; - | ^^^^^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui-toml/blacklisted_names_append/clippy.toml b/tests/ui-toml/blacklisted_names_append/clippy.toml deleted file mode 100644 index 0e052ef50..000000000 --- a/tests/ui-toml/blacklisted_names_append/clippy.toml +++ /dev/null @@ -1 +0,0 @@ -blacklisted-names = ["ducks", ".."] diff --git a/tests/ui-toml/blacklisted_names_replace/blacklisted_names.stderr b/tests/ui-toml/blacklisted_names_replace/blacklisted_names.stderr deleted file mode 100644 index ec6f7f084..000000000 --- a/tests/ui-toml/blacklisted_names_replace/blacklisted_names.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: use of a blacklisted/placeholder name `ducks` - --> $DIR/blacklisted_names.rs:7:9 - | -LL | let ducks = ["quack", "quack"]; - | ^^^^^ - | - = note: `-D clippy::blacklisted-name` implied by `-D warnings` - -error: aborting due to previous error - diff --git a/tests/ui-toml/blacklisted_names_replace/clippy.toml b/tests/ui-toml/blacklisted_names_replace/clippy.toml deleted file mode 100644 index 4582f1c06..000000000 --- a/tests/ui-toml/blacklisted_names_replace/clippy.toml +++ /dev/null @@ -1 +0,0 @@ -blacklisted-names = ["ducks"] diff --git a/tests/ui-toml/conf_deprecated_key/clippy.toml b/tests/ui-toml/conf_deprecated_key/clippy.toml index ac47b1950..d79a98d05 100644 --- a/tests/ui-toml/conf_deprecated_key/clippy.toml +++ b/tests/ui-toml/conf_deprecated_key/clippy.toml @@ -1,5 +1,6 @@ -# that one is an error -cyclomatic-complexity-threshold = 42 +# Expect errors from these deprecated configs +cyclomatic-complexity-threshold = 2 +blacklisted-names = [ "..", "wibble" ] # that one is white-listed [third-party] diff --git a/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.rs b/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.rs index f328e4d9d..b4e677ea1 100644 --- a/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.rs +++ b/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.rs @@ -1 +1,11 @@ fn main() {} + +#[warn(clippy::cognitive_complexity)] +fn cognitive_complexity() { + let x = vec![1, 2, 3]; + for i in x { + if i == 1 { + println!("{}", i); + } + } +} diff --git a/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr b/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr index 90021a034..4c560299e 100644 --- a/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr +++ b/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr @@ -1,4 +1,15 @@ -error: error reading Clippy's configuration file `$DIR/clippy.toml`: deprecated field `cyclomatic-complexity-threshold`. Please use `cognitive-complexity-threshold` instead +warning: error reading Clippy's configuration file `$DIR/clippy.toml`: deprecated field `cyclomatic-complexity-threshold`. Please use `cognitive-complexity-threshold` instead -error: aborting due to previous error +warning: error reading Clippy's configuration file `$DIR/clippy.toml`: deprecated field `blacklisted-names`. Please use `disallowed-names` instead + +error: the function has a cognitive complexity of (3/2) + --> $DIR/conf_deprecated_key.rs:4:4 + | +LL | fn cognitive_complexity() { + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::cognitive-complexity` implied by `-D warnings` + = help: you could split it up into multiple smaller functions + +error: aborting due to previous error; 2 warnings emitted diff --git a/tests/ui-toml/disallowed_names_append/clippy.toml b/tests/ui-toml/disallowed_names_append/clippy.toml new file mode 100644 index 000000000..6df96a3c2 --- /dev/null +++ b/tests/ui-toml/disallowed_names_append/clippy.toml @@ -0,0 +1 @@ +disallowed-names = ["ducks", ".."] diff --git a/tests/ui-toml/blacklisted_names_replace/blacklisted_names.rs b/tests/ui-toml/disallowed_names_append/disallowed_names.rs similarity index 72% rename from tests/ui-toml/blacklisted_names_replace/blacklisted_names.rs rename to tests/ui-toml/disallowed_names_append/disallowed_names.rs index fb2395cf9..a2e2b46c4 100644 --- a/tests/ui-toml/blacklisted_names_replace/blacklisted_names.rs +++ b/tests/ui-toml/disallowed_names_append/disallowed_names.rs @@ -1,9 +1,9 @@ -#[warn(clippy::blacklisted_name)] +#[warn(clippy::disallowed_names)] fn main() { // `foo` is part of the default configuration let foo = "bar"; - // `ducks` was unrightfully blacklisted + // `ducks` was unrightfully disallowed let ducks = ["quack", "quack"]; // `fox` is okay let fox = ["what", "does", "the", "fox", "say", "?"]; diff --git a/tests/ui-toml/disallowed_names_append/disallowed_names.stderr b/tests/ui-toml/disallowed_names_append/disallowed_names.stderr new file mode 100644 index 000000000..23c3e96a8 --- /dev/null +++ b/tests/ui-toml/disallowed_names_append/disallowed_names.stderr @@ -0,0 +1,16 @@ +error: use of a disallowed/placeholder name `foo` + --> $DIR/disallowed_names.rs:5:9 + | +LL | let foo = "bar"; + | ^^^ + | + = note: `-D clippy::disallowed-names` implied by `-D warnings` + +error: use of a disallowed/placeholder name `ducks` + --> $DIR/disallowed_names.rs:7:9 + | +LL | let ducks = ["quack", "quack"]; + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui-toml/disallowed_names_replace/clippy.toml b/tests/ui-toml/disallowed_names_replace/clippy.toml new file mode 100644 index 000000000..a1c515652 --- /dev/null +++ b/tests/ui-toml/disallowed_names_replace/clippy.toml @@ -0,0 +1 @@ +disallowed-names = ["ducks"] diff --git a/tests/ui-toml/blacklisted_names_append/blacklisted_names.rs b/tests/ui-toml/disallowed_names_replace/disallowed_names.rs similarity index 72% rename from tests/ui-toml/blacklisted_names_append/blacklisted_names.rs rename to tests/ui-toml/disallowed_names_replace/disallowed_names.rs index fb2395cf9..a2e2b46c4 100644 --- a/tests/ui-toml/blacklisted_names_append/blacklisted_names.rs +++ b/tests/ui-toml/disallowed_names_replace/disallowed_names.rs @@ -1,9 +1,9 @@ -#[warn(clippy::blacklisted_name)] +#[warn(clippy::disallowed_names)] fn main() { // `foo` is part of the default configuration let foo = "bar"; - // `ducks` was unrightfully blacklisted + // `ducks` was unrightfully disallowed let ducks = ["quack", "quack"]; // `fox` is okay let fox = ["what", "does", "the", "fox", "say", "?"]; diff --git a/tests/ui-toml/disallowed_names_replace/disallowed_names.stderr b/tests/ui-toml/disallowed_names_replace/disallowed_names.stderr new file mode 100644 index 000000000..d961fa340 --- /dev/null +++ b/tests/ui-toml/disallowed_names_replace/disallowed_names.stderr @@ -0,0 +1,10 @@ +error: use of a disallowed/placeholder name `ducks` + --> $DIR/disallowed_names.rs:7:9 + | +LL | let ducks = ["quack", "quack"]; + | ^^^^^ + | + = note: `-D clippy::disallowed-names` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui-toml/duplicated_keys/clippy.toml b/tests/ui-toml/duplicated_keys/clippy.toml new file mode 100644 index 000000000..63a893cc6 --- /dev/null +++ b/tests/ui-toml/duplicated_keys/clippy.toml @@ -0,0 +1,5 @@ +cognitive-complexity-threshold = 2 +# This is the deprecated name for the same key +cyclomatic-complexity-threshold = 3 +# Check we get duplication warning regardless of order +cognitive-complexity-threshold = 4 diff --git a/tests/ui-toml/duplicated_keys/duplicated_keys.rs b/tests/ui-toml/duplicated_keys/duplicated_keys.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/tests/ui-toml/duplicated_keys/duplicated_keys.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/ui-toml/duplicated_keys/duplicated_keys.stderr b/tests/ui-toml/duplicated_keys/duplicated_keys.stderr new file mode 100644 index 000000000..d99490a24 --- /dev/null +++ b/tests/ui-toml/duplicated_keys/duplicated_keys.stderr @@ -0,0 +1,8 @@ +error: error reading Clippy's configuration file `$DIR/clippy.toml`: duplicate field `cognitive_complexity_threshold` (provided as `cyclomatic_complexity_threshold`) + +error: error reading Clippy's configuration file `$DIR/clippy.toml`: duplicate field `cognitive-complexity-threshold` + +warning: error reading Clippy's configuration file `$DIR/clippy.toml`: deprecated field `cyclomatic-complexity-threshold`. Please use `cognitive-complexity-threshold` instead + +error: aborting due to 2 previous errors; 1 warning emitted + diff --git a/tests/ui-toml/expect_used/expect_used.stderr b/tests/ui-toml/expect_used/expect_used.stderr index 9cb2199ed..c5d95cb8a 100644 --- a/tests/ui-toml/expect_used/expect_used.stderr +++ b/tests/ui-toml/expect_used/expect_used.stderr @@ -5,7 +5,7 @@ LL | let _ = opt.expect(""); | ^^^^^^^^^^^^^^ | = note: `-D clippy::expect-used` implied by `-D warnings` - = help: if this value is an `None`, it will panic + = help: if this value is `None`, it will panic error: used `expect()` on `a Result` value --> $DIR/expect_used.rs:11:13 diff --git a/tests/ui-toml/toml_blacklist/clippy.toml b/tests/ui-toml/toml_blacklist/clippy.toml deleted file mode 100644 index 6abe5a3bb..000000000 --- a/tests/ui-toml/toml_blacklist/clippy.toml +++ /dev/null @@ -1 +0,0 @@ -blacklisted-names = ["toto", "tata", "titi"] diff --git a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr b/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr deleted file mode 100644 index 84ba77851..000000000 --- a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.stderr +++ /dev/null @@ -1,46 +0,0 @@ -error: use of a blacklisted/placeholder name `toto` - --> $DIR/conf_french_blacklisted_name.rs:6:9 - | -LL | fn test(toto: ()) {} - | ^^^^ - | - = note: `-D clippy::blacklisted-name` implied by `-D warnings` - -error: use of a blacklisted/placeholder name `toto` - --> $DIR/conf_french_blacklisted_name.rs:9:9 - | -LL | let toto = 42; - | ^^^^ - -error: use of a blacklisted/placeholder name `tata` - --> $DIR/conf_french_blacklisted_name.rs:10:9 - | -LL | let tata = 42; - | ^^^^ - -error: use of a blacklisted/placeholder name `titi` - --> $DIR/conf_french_blacklisted_name.rs:11:9 - | -LL | let titi = 42; - | ^^^^ - -error: use of a blacklisted/placeholder name `toto` - --> $DIR/conf_french_blacklisted_name.rs:17:10 - | -LL | (toto, Some(tata), titi @ Some(_)) => (), - | ^^^^ - -error: use of a blacklisted/placeholder name `tata` - --> $DIR/conf_french_blacklisted_name.rs:17:21 - | -LL | (toto, Some(tata), titi @ Some(_)) => (), - | ^^^^ - -error: use of a blacklisted/placeholder name `titi` - --> $DIR/conf_french_blacklisted_name.rs:17:28 - | -LL | (toto, Some(tata), titi @ Some(_)) => (), - | ^^^^ - -error: aborting due to 7 previous errors - diff --git a/tests/ui-toml/toml_disallow/clippy.toml b/tests/ui-toml/toml_disallow/clippy.toml new file mode 100644 index 000000000..e4f0cb6df --- /dev/null +++ b/tests/ui-toml/toml_disallow/clippy.toml @@ -0,0 +1 @@ +disallowed-names = ["toto", "tata", "titi"] diff --git a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs b/tests/ui-toml/toml_disallow/conf_french_disallowed_name.rs similarity index 90% rename from tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs rename to tests/ui-toml/toml_disallow/conf_french_disallowed_name.rs index cb35d0e85..2f86b3eda 100644 --- a/tests/ui-toml/toml_blacklist/conf_french_blacklisted_name.rs +++ b/tests/ui-toml/toml_disallow/conf_french_disallowed_name.rs @@ -1,7 +1,7 @@ #![allow(dead_code)] #![allow(clippy::single_match)] #![allow(unused_variables)] -#![warn(clippy::blacklisted_name)] +#![warn(clippy::disallowed_names)] fn test(toto: ()) {} diff --git a/tests/ui-toml/toml_disallow/conf_french_disallowed_name.stderr b/tests/ui-toml/toml_disallow/conf_french_disallowed_name.stderr new file mode 100644 index 000000000..9082c1c54 --- /dev/null +++ b/tests/ui-toml/toml_disallow/conf_french_disallowed_name.stderr @@ -0,0 +1,46 @@ +error: use of a disallowed/placeholder name `toto` + --> $DIR/conf_french_disallowed_name.rs:6:9 + | +LL | fn test(toto: ()) {} + | ^^^^ + | + = note: `-D clippy::disallowed-names` implied by `-D warnings` + +error: use of a disallowed/placeholder name `toto` + --> $DIR/conf_french_disallowed_name.rs:9:9 + | +LL | let toto = 42; + | ^^^^ + +error: use of a disallowed/placeholder name `tata` + --> $DIR/conf_french_disallowed_name.rs:10:9 + | +LL | let tata = 42; + | ^^^^ + +error: use of a disallowed/placeholder name `titi` + --> $DIR/conf_french_disallowed_name.rs:11:9 + | +LL | let titi = 42; + | ^^^^ + +error: use of a disallowed/placeholder name `toto` + --> $DIR/conf_french_disallowed_name.rs:17:10 + | +LL | (toto, Some(tata), titi @ Some(_)) => (), + | ^^^^ + +error: use of a disallowed/placeholder name `tata` + --> $DIR/conf_french_disallowed_name.rs:17:21 + | +LL | (toto, Some(tata), titi @ Some(_)) => (), + | ^^^^ + +error: use of a disallowed/placeholder name `titi` + --> $DIR/conf_french_disallowed_name.rs:17:28 + | +LL | (toto, Some(tata), titi @ Some(_)) => (), + | ^^^^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index fe5139c47..9f8e778b3 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -12,6 +12,7 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie cognitive-complexity-threshold cyclomatic-complexity-threshold disallowed-methods + disallowed-names disallowed-types doc-valid-idents enable-raw-pointer-heuristic-for-send diff --git a/tests/ui/assertions_on_result_states.fixed b/tests/ui/assertions_on_result_states.fixed index 7bde72e4b..795f435f2 100644 --- a/tests/ui/assertions_on_result_states.fixed +++ b/tests/ui/assertions_on_result_states.fixed @@ -27,6 +27,14 @@ fn main() { let r: Result = Ok(Foo); assert!(r.is_ok()); + // test ok with some messages + let r: Result = Ok(Foo); + assert!(r.is_ok(), "oops"); + + // test ok with unit error + let r: Result = Ok(Foo); + assert!(r.is_ok()); + // test temporary ok fn get_ok() -> Result { Ok(Foo) diff --git a/tests/ui/assertions_on_result_states.rs b/tests/ui/assertions_on_result_states.rs index 4c5af81ef..1101aec1e 100644 --- a/tests/ui/assertions_on_result_states.rs +++ b/tests/ui/assertions_on_result_states.rs @@ -27,6 +27,14 @@ fn main() { let r: Result = Ok(Foo); assert!(r.is_ok()); + // test ok with some messages + let r: Result = Ok(Foo); + assert!(r.is_ok(), "oops"); + + // test ok with unit error + let r: Result = Ok(Foo); + assert!(r.is_ok()); + // test temporary ok fn get_ok() -> Result { Ok(Foo) diff --git a/tests/ui/assertions_on_result_states.stderr b/tests/ui/assertions_on_result_states.stderr index 13c2dd877..97a5f3dfc 100644 --- a/tests/ui/assertions_on_result_states.stderr +++ b/tests/ui/assertions_on_result_states.stderr @@ -7,31 +7,31 @@ LL | assert!(r.is_ok()); = note: `-D clippy::assertions-on-result-states` implied by `-D warnings` error: called `assert!` with `Result::is_ok` - --> $DIR/assertions_on_result_states.rs:34:5 + --> $DIR/assertions_on_result_states.rs:42:5 | LL | assert!(get_ok().is_ok()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `get_ok().unwrap()` error: called `assert!` with `Result::is_ok` - --> $DIR/assertions_on_result_states.rs:37:5 + --> $DIR/assertions_on_result_states.rs:45:5 | LL | assert!(get_ok_macro!().is_ok()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `get_ok_macro!().unwrap()` error: called `assert!` with `Result::is_ok` - --> $DIR/assertions_on_result_states.rs:50:5 + --> $DIR/assertions_on_result_states.rs:58:5 | LL | assert!(r.is_ok()); | ^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap()` error: called `assert!` with `Result::is_ok` - --> $DIR/assertions_on_result_states.rs:56:9 + --> $DIR/assertions_on_result_states.rs:64:9 | LL | assert!(r.is_ok()); | ^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap()` error: called `assert!` with `Result::is_err` - --> $DIR/assertions_on_result_states.rs:64:5 + --> $DIR/assertions_on_result_states.rs:72:5 | LL | assert!(r.is_err()); | ^^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap_err()` diff --git a/tests/ui/blacklisted_name.stderr b/tests/ui/blacklisted_name.stderr deleted file mode 100644 index 70dbdaece..000000000 --- a/tests/ui/blacklisted_name.stderr +++ /dev/null @@ -1,88 +0,0 @@ -error: use of a blacklisted/placeholder name `foo` - --> $DIR/blacklisted_name.rs:11:9 - | -LL | fn test(foo: ()) {} - | ^^^ - | - = note: `-D clippy::blacklisted-name` implied by `-D warnings` - -error: use of a blacklisted/placeholder name `foo` - --> $DIR/blacklisted_name.rs:14:9 - | -LL | let foo = 42; - | ^^^ - -error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:15:9 - | -LL | let baz = 42; - | ^^^ - -error: use of a blacklisted/placeholder name `quux` - --> $DIR/blacklisted_name.rs:16:9 - | -LL | let quux = 42; - | ^^^^ - -error: use of a blacklisted/placeholder name `foo` - --> $DIR/blacklisted_name.rs:27:10 - | -LL | (foo, Some(baz), quux @ Some(_)) => (), - | ^^^ - -error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:27:20 - | -LL | (foo, Some(baz), quux @ Some(_)) => (), - | ^^^ - -error: use of a blacklisted/placeholder name `quux` - --> $DIR/blacklisted_name.rs:27:26 - | -LL | (foo, Some(baz), quux @ Some(_)) => (), - | ^^^^ - -error: use of a blacklisted/placeholder name `foo` - --> $DIR/blacklisted_name.rs:32:19 - | -LL | fn issue_1647(mut foo: u8) { - | ^^^ - -error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:33:13 - | -LL | let mut baz = 0; - | ^^^ - -error: use of a blacklisted/placeholder name `quux` - --> $DIR/blacklisted_name.rs:34:21 - | -LL | if let Some(mut quux) = Some(42) {} - | ^^^^ - -error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:38:13 - | -LL | let ref baz = 0; - | ^^^ - -error: use of a blacklisted/placeholder name `quux` - --> $DIR/blacklisted_name.rs:39:21 - | -LL | if let Some(ref quux) = Some(42) {} - | ^^^^ - -error: use of a blacklisted/placeholder name `baz` - --> $DIR/blacklisted_name.rs:43:17 - | -LL | let ref mut baz = 0; - | ^^^ - -error: use of a blacklisted/placeholder name `quux` - --> $DIR/blacklisted_name.rs:44:25 - | -LL | if let Some(ref mut quux) = Some(42) {} - | ^^^^ - -error: aborting due to 14 previous errors - diff --git a/tests/ui/borrow_box.rs b/tests/ui/borrow_box.rs index b606f773c..35ed87b0f 100644 --- a/tests/ui/borrow_box.rs +++ b/tests/ui/borrow_box.rs @@ -1,5 +1,5 @@ #![deny(clippy::borrowed_box)] -#![allow(clippy::blacklisted_name)] +#![allow(clippy::disallowed_names)] #![allow(unused_variables)] #![allow(dead_code)] diff --git a/tests/ui/box_collection.rs b/tests/ui/box_collection.rs index 1a74cdb3f..0780c8f05 100644 --- a/tests/ui/box_collection.rs +++ b/tests/ui/box_collection.rs @@ -2,7 +2,7 @@ #![allow( clippy::boxed_local, clippy::needless_pass_by_value, - clippy::blacklisted_name, + clippy::disallowed_names, unused )] diff --git a/tests/ui/cast_abs_to_unsigned.fixed b/tests/ui/cast_abs_to_unsigned.fixed index a68b32b09..7ecefd7b1 100644 --- a/tests/ui/cast_abs_to_unsigned.fixed +++ b/tests/ui/cast_abs_to_unsigned.fixed @@ -26,4 +26,6 @@ fn main() { let _ = a.unsigned_abs() as u32; let _ = a.unsigned_abs() as u64; let _ = a.unsigned_abs() as u128; + + let _ = (x as i64 - y as i64).unsigned_abs() as u32; } diff --git a/tests/ui/cast_abs_to_unsigned.rs b/tests/ui/cast_abs_to_unsigned.rs index 110fbc6c2..30c603fca 100644 --- a/tests/ui/cast_abs_to_unsigned.rs +++ b/tests/ui/cast_abs_to_unsigned.rs @@ -26,4 +26,6 @@ fn main() { let _ = a.abs() as u32; let _ = a.abs() as u64; let _ = a.abs() as u128; + + let _ = (x as i64 - y as i64).abs() as u32; } diff --git a/tests/ui/cast_abs_to_unsigned.stderr b/tests/ui/cast_abs_to_unsigned.stderr index 02c24e106..045537745 100644 --- a/tests/ui/cast_abs_to_unsigned.stderr +++ b/tests/ui/cast_abs_to_unsigned.stderr @@ -96,5 +96,11 @@ error: casting the result of `isize::abs()` to u128 LL | let _ = a.abs() as u128; | ^^^^^^^ help: replace with: `a.unsigned_abs()` -error: aborting due to 16 previous errors +error: casting the result of `i64::abs()` to u32 + --> $DIR/cast_abs_to_unsigned.rs:30:13 + | +LL | let _ = (x as i64 - y as i64).abs() as u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `(x as i64 - y as i64).unsigned_abs()` + +error: aborting due to 17 previous errors diff --git a/tests/ui/clone_on_copy.fixed b/tests/ui/clone_on_copy.fixed index dc0627626..72b122270 100644 --- a/tests/ui/clone_on_copy.fixed +++ b/tests/ui/clone_on_copy.fixed @@ -21,7 +21,7 @@ fn is_ascii(ch: char) -> bool { ch.is_ascii() } -fn clone_on_copy() { +fn clone_on_copy() -> Option<(i32)> { 42; vec![1].clone(); // ok, not a Copy type @@ -71,4 +71,9 @@ fn clone_on_copy() { // Issue #5436 let mut vec = Vec::new(); vec.push(42); + + // Issue #9277 + let opt: &Option = &None; + let value = (*opt)?; // operator precedence needed (*opt)? + None } diff --git a/tests/ui/clone_on_copy.rs b/tests/ui/clone_on_copy.rs index 8c39d0d55..03e210eba 100644 --- a/tests/ui/clone_on_copy.rs +++ b/tests/ui/clone_on_copy.rs @@ -21,7 +21,7 @@ fn is_ascii(ch: char) -> bool { ch.is_ascii() } -fn clone_on_copy() { +fn clone_on_copy() -> Option<(i32)> { 42.clone(); vec![1].clone(); // ok, not a Copy type @@ -71,4 +71,9 @@ fn clone_on_copy() { // Issue #5436 let mut vec = Vec::new(); vec.push(42.clone()); + + // Issue #9277 + let opt: &Option = &None; + let value = opt.clone()?; // operator precedence needed (*opt)? + None } diff --git a/tests/ui/clone_on_copy.stderr b/tests/ui/clone_on_copy.stderr index 861543d0a..42ae22777 100644 --- a/tests/ui/clone_on_copy.stderr +++ b/tests/ui/clone_on_copy.stderr @@ -48,5 +48,11 @@ error: using `clone` on type `i32` which implements the `Copy` trait LL | vec.push(42.clone()); | ^^^^^^^^^^ help: try removing the `clone` call: `42` -error: aborting due to 8 previous errors +error: using `clone` on type `std::option::Option` which implements the `Copy` trait + --> $DIR/clone_on_copy.rs:77:17 + | +LL | let value = opt.clone()?; // operator precedence needed (*opt)? + | ^^^^^^^^^^^ help: try dereferencing it: `(*opt)` + +error: aborting due to 9 previous errors diff --git a/tests/ui/crashes/ice-2760.rs b/tests/ui/crashes/ice-2760.rs index f1a229f3f..61ef24804 100644 --- a/tests/ui/crashes/ice-2760.rs +++ b/tests/ui/crashes/ice-2760.rs @@ -1,6 +1,6 @@ #![allow( unused_variables, - clippy::blacklisted_name, + clippy::disallowed_names, clippy::needless_pass_by_value, dead_code )] diff --git a/tests/ui/crashes/ice-3462.rs b/tests/ui/crashes/ice-3462.rs index 02c49aa0d..b40205288 100644 --- a/tests/ui/crashes/ice-3462.rs +++ b/tests/ui/crashes/ice-3462.rs @@ -1,5 +1,5 @@ #![warn(clippy::all)] -#![allow(clippy::blacklisted_name, clippy::equatable_if_let)] +#![allow(clippy::disallowed_names, clippy::equatable_if_let)] #![allow(unused)] /// Test for https://github.com/rust-lang/rust-clippy/issues/3462 diff --git a/tests/ui/crashes/regressions.rs b/tests/ui/crashes/regressions.rs index 6f9d98bbf..55a8b4034 100644 --- a/tests/ui/crashes/regressions.rs +++ b/tests/ui/crashes/regressions.rs @@ -1,4 +1,4 @@ -#![allow(clippy::blacklisted_name)] +#![allow(clippy::disallowed_names)] pub fn foo(bar: *const u8) { println!("{:#p}", bar); diff --git a/tests/ui/def_id_nocore.rs b/tests/ui/def_id_nocore.rs index 156c88e2e..a7da8f89a 100644 --- a/tests/ui/def_id_nocore.rs +++ b/tests/ui/def_id_nocore.rs @@ -1,4 +1,3 @@ -// ignore-windows // ignore-macos #![feature(no_core, lang_items, start)] diff --git a/tests/ui/def_id_nocore.stderr b/tests/ui/def_id_nocore.stderr index 40d355e9a..6210d7c6c 100644 --- a/tests/ui/def_id_nocore.stderr +++ b/tests/ui/def_id_nocore.stderr @@ -1,5 +1,5 @@ error: methods called `as_*` usually take `self` by reference or `self` by mutable reference - --> $DIR/def_id_nocore.rs:28:19 + --> $DIR/def_id_nocore.rs:27:19 | LL | pub fn as_ref(self) -> &'static str { | ^^^^ diff --git a/tests/ui/default_trait_access.fixed b/tests/ui/default_trait_access.fixed index 264dd4efa..fce66eb17 100644 --- a/tests/ui/default_trait_access.fixed +++ b/tests/ui/default_trait_access.fixed @@ -1,8 +1,12 @@ // run-rustfix +// aux-build: proc_macro_with_span.rs #![allow(unused_imports, dead_code)] #![deny(clippy::default_trait_access)] +extern crate proc_macro_with_span; + +use proc_macro_with_span::with_span; use std::default; use std::default::Default as D2; use std::string; @@ -51,6 +55,8 @@ fn main() { ..Default::default() }; + let _s21: String = with_span!(s Default::default()); + println!( "[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}]", s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, diff --git a/tests/ui/default_trait_access.rs b/tests/ui/default_trait_access.rs index a0930fab8..3e8e898b7 100644 --- a/tests/ui/default_trait_access.rs +++ b/tests/ui/default_trait_access.rs @@ -1,8 +1,12 @@ // run-rustfix +// aux-build: proc_macro_with_span.rs #![allow(unused_imports, dead_code)] #![deny(clippy::default_trait_access)] +extern crate proc_macro_with_span; + +use proc_macro_with_span::with_span; use std::default; use std::default::Default as D2; use std::string; @@ -51,6 +55,8 @@ fn main() { ..Default::default() }; + let _s21: String = with_span!(s Default::default()); + println!( "[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}]", s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, diff --git a/tests/ui/default_trait_access.stderr b/tests/ui/default_trait_access.stderr index df8a5b94d..3493de37a 100644 --- a/tests/ui/default_trait_access.stderr +++ b/tests/ui/default_trait_access.stderr @@ -1,53 +1,53 @@ error: calling `std::string::String::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:11:22 + --> $DIR/default_trait_access.rs:15:22 | LL | let s1: String = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` | note: the lint level is defined here - --> $DIR/default_trait_access.rs:4:9 + --> $DIR/default_trait_access.rs:5:9 | LL | #![deny(clippy::default_trait_access)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: calling `std::string::String::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:15:22 + --> $DIR/default_trait_access.rs:19:22 | LL | let s3: String = D2::default(); | ^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: calling `std::string::String::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:17:22 + --> $DIR/default_trait_access.rs:21:22 | LL | let s4: String = std::default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: calling `std::string::String::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:21:22 + --> $DIR/default_trait_access.rs:25:22 | LL | let s6: String = default::Default::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()` error: calling `GenericDerivedDefault::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:31:46 + --> $DIR/default_trait_access.rs:35:46 | LL | let s11: GenericDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `GenericDerivedDefault::default()` error: calling `TupleDerivedDefault::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:37:36 + --> $DIR/default_trait_access.rs:41:36 | LL | let s14: TupleDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `TupleDerivedDefault::default()` error: calling `ArrayDerivedDefault::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:39:36 + --> $DIR/default_trait_access.rs:43:36 | LL | let s15: ArrayDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `ArrayDerivedDefault::default()` error: calling `TupleStructDerivedDefault::default()` is more clear than this expression - --> $DIR/default_trait_access.rs:43:42 + --> $DIR/default_trait_access.rs:47:42 | LL | let s17: TupleStructDerivedDefault = Default::default(); | ^^^^^^^^^^^^^^^^^^ help: try: `TupleStructDerivedDefault::default()` diff --git a/tests/ui/blacklisted_name.rs b/tests/ui/disallowed_names.rs similarity index 92% rename from tests/ui/blacklisted_name.rs rename to tests/ui/disallowed_names.rs index 27df732a0..e937c49f3 100644 --- a/tests/ui/blacklisted_name.rs +++ b/tests/ui/disallowed_names.rs @@ -6,7 +6,7 @@ unused_mut, unused_variables )] -#![warn(clippy::blacklisted_name)] +#![warn(clippy::disallowed_names)] fn test(foo: ()) {} @@ -46,7 +46,7 @@ fn issue_1647_ref_mut() { mod tests { fn issue_7305() { - // `blacklisted_name` lint should not be triggered inside of the test code. + // `disallowed_names` lint should not be triggered inside of the test code. let foo = 0; // Check that even in nested functions warning is still not triggered. diff --git a/tests/ui/disallowed_names.stderr b/tests/ui/disallowed_names.stderr new file mode 100644 index 000000000..78cb55096 --- /dev/null +++ b/tests/ui/disallowed_names.stderr @@ -0,0 +1,88 @@ +error: use of a disallowed/placeholder name `foo` + --> $DIR/disallowed_names.rs:11:9 + | +LL | fn test(foo: ()) {} + | ^^^ + | + = note: `-D clippy::disallowed-names` implied by `-D warnings` + +error: use of a disallowed/placeholder name `foo` + --> $DIR/disallowed_names.rs:14:9 + | +LL | let foo = 42; + | ^^^ + +error: use of a disallowed/placeholder name `baz` + --> $DIR/disallowed_names.rs:15:9 + | +LL | let baz = 42; + | ^^^ + +error: use of a disallowed/placeholder name `quux` + --> $DIR/disallowed_names.rs:16:9 + | +LL | let quux = 42; + | ^^^^ + +error: use of a disallowed/placeholder name `foo` + --> $DIR/disallowed_names.rs:27:10 + | +LL | (foo, Some(baz), quux @ Some(_)) => (), + | ^^^ + +error: use of a disallowed/placeholder name `baz` + --> $DIR/disallowed_names.rs:27:20 + | +LL | (foo, Some(baz), quux @ Some(_)) => (), + | ^^^ + +error: use of a disallowed/placeholder name `quux` + --> $DIR/disallowed_names.rs:27:26 + | +LL | (foo, Some(baz), quux @ Some(_)) => (), + | ^^^^ + +error: use of a disallowed/placeholder name `foo` + --> $DIR/disallowed_names.rs:32:19 + | +LL | fn issue_1647(mut foo: u8) { + | ^^^ + +error: use of a disallowed/placeholder name `baz` + --> $DIR/disallowed_names.rs:33:13 + | +LL | let mut baz = 0; + | ^^^ + +error: use of a disallowed/placeholder name `quux` + --> $DIR/disallowed_names.rs:34:21 + | +LL | if let Some(mut quux) = Some(42) {} + | ^^^^ + +error: use of a disallowed/placeholder name `baz` + --> $DIR/disallowed_names.rs:38:13 + | +LL | let ref baz = 0; + | ^^^ + +error: use of a disallowed/placeholder name `quux` + --> $DIR/disallowed_names.rs:39:21 + | +LL | if let Some(ref quux) = Some(42) {} + | ^^^^ + +error: use of a disallowed/placeholder name `baz` + --> $DIR/disallowed_names.rs:43:17 + | +LL | let ref mut baz = 0; + | ^^^ + +error: use of a disallowed/placeholder name `quux` + --> $DIR/disallowed_names.rs:44:25 + | +LL | if let Some(ref mut quux) = Some(42) {} + | ^^^^ + +error: aborting due to 14 previous errors + diff --git a/tests/ui/diverging_sub_expression.rs b/tests/ui/diverging_sub_expression.rs index e27f9fea7..e8f992e6d 100644 --- a/tests/ui/diverging_sub_expression.rs +++ b/tests/ui/diverging_sub_expression.rs @@ -1,5 +1,5 @@ #![warn(clippy::diverging_sub_expression)] -#![allow(clippy::match_same_arms, clippy::logic_bug)] +#![allow(clippy::match_same_arms, clippy::overly_complex_bool_expr)] #[allow(clippy::empty_loop)] fn diverge() -> ! { loop {} diff --git a/tests/ui/empty_loop_no_std.rs b/tests/ui/empty_loop_no_std.rs index 235e0fc51..e742b396f 100644 --- a/tests/ui/empty_loop_no_std.rs +++ b/tests/ui/empty_loop_no_std.rs @@ -1,6 +1,5 @@ // compile-flags: -Clink-arg=-nostartfiles // ignore-macos -// ignore-windows #![warn(clippy::empty_loop)] #![feature(lang_items, start, libc)] diff --git a/tests/ui/empty_loop_no_std.stderr b/tests/ui/empty_loop_no_std.stderr index 520248fcb..5ded35a6f 100644 --- a/tests/ui/empty_loop_no_std.stderr +++ b/tests/ui/empty_loop_no_std.stderr @@ -1,5 +1,5 @@ error: empty `loop {}` wastes CPU cycles - --> $DIR/empty_loop_no_std.rs:14:5 + --> $DIR/empty_loop_no_std.rs:13:5 | LL | loop {} | ^^^^^^^ @@ -8,7 +8,7 @@ LL | loop {} = help: you should either use `panic!()` or add a call pausing or sleeping the thread to the loop body error: empty `loop {}` wastes CPU cycles - --> $DIR/empty_loop_no_std.rs:26:5 + --> $DIR/empty_loop_no_std.rs:25:5 | LL | loop {} | ^^^^^^^ diff --git a/tests/ui/expect.stderr b/tests/ui/expect.stderr index 9d3fc7df1..ab28aac45 100644 --- a/tests/ui/expect.stderr +++ b/tests/ui/expect.stderr @@ -5,7 +5,7 @@ LL | let _ = opt.expect(""); | ^^^^^^^^^^^^^^ | = note: `-D clippy::expect-used` implied by `-D warnings` - = help: if this value is an `None`, it will panic + = help: if this value is `None`, it will panic error: used `expect()` on `a Result` value --> $DIR/expect.rs:10:13 diff --git a/tests/ui/expect_tool_lint_rfc_2383.rs b/tests/ui/expect_tool_lint_rfc_2383.rs index 28b37f96e..0415e33b3 100644 --- a/tests/ui/expect_tool_lint_rfc_2383.rs +++ b/tests/ui/expect_tool_lint_rfc_2383.rs @@ -98,7 +98,7 @@ mod clippy_ok { let _ = if true { 42 } else { 42 }; } - #[expect(clippy::logic_bug)] + #[expect(clippy::overly_complex_bool_expr)] fn burger() { let a = false; let b = true; @@ -127,7 +127,7 @@ mod clippy_warn { let _ = if true { 33 } else { 42 }; } - #[expect(clippy::logic_bug)] + #[expect(clippy::overly_complex_bool_expr)] fn burger() { let a = false; let b = true; diff --git a/tests/ui/expect_tool_lint_rfc_2383.stderr b/tests/ui/expect_tool_lint_rfc_2383.stderr index db29e85a8..7ce9e855b 100644 --- a/tests/ui/expect_tool_lint_rfc_2383.stderr +++ b/tests/ui/expect_tool_lint_rfc_2383.stderr @@ -33,8 +33,8 @@ LL | #[expect(clippy::if_same_then_else)] error: this lint expectation is unfulfilled --> $DIR/expect_tool_lint_rfc_2383.rs:130:14 | -LL | #[expect(clippy::logic_bug)] - | ^^^^^^^^^^^^^^^^^ +LL | #[expect(clippy::overly_complex_bool_expr)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/explicit_auto_deref.fixed b/tests/ui/explicit_auto_deref.fixed index a650fdc1f..d1d35e5c0 100644 --- a/tests/ui/explicit_auto_deref.fixed +++ b/tests/ui/explicit_auto_deref.fixed @@ -1,5 +1,6 @@ // run-rustfix +#![feature(closure_lifetime_binder)] #![warn(clippy::explicit_auto_deref)] #![allow( dead_code, @@ -67,6 +68,8 @@ fn main() { let s = String::new(); let _: &str = &s; + let _: &str = &{ String::new() }; + let _: &str = &mut { String::new() }; let _ = &*s; // Don't lint. Inferred type would change. let _: &_ = &*s; // Don't lint. Inferred type would change. @@ -215,4 +218,52 @@ fn main() { let s = &"str"; let _ = || return *s; let _ = || -> &'static str { return s }; + + struct X; + struct Y(X); + impl core::ops::Deref for Y { + type Target = X; + fn deref(&self) -> &Self::Target { + &self.0 + } + } + let _: &X = &*{ Y(X) }; + let _: &X = &*match 0 { + #[rustfmt::skip] + 0 => { Y(X) }, + _ => panic!(), + }; + let _: &X = &*if true { Y(X) } else { panic!() }; + + fn deref_to_u>(x: &T) -> &U { + x + } + + let _ = |x: &'static Box>| -> &'static dyn Iterator { &**x }; + fn ret_any(x: &Box) -> &dyn std::any::Any { + &**x + } + + let x = String::new(); + let _: *const str = &*x; + + struct S7([u32; 1]); + impl core::ops::Deref for S7 { + type Target = [u32; 1]; + fn deref(&self) -> &Self::Target { + &self.0 + } + } + let x = S7([0]); + let _: &[u32] = &*x; + + let c1 = |_: &Vec<&u32>| {}; + let x = &&vec![&1u32]; + c1(x); + let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<&'b u32> { + if b { + return x; + } + x + }; } diff --git a/tests/ui/explicit_auto_deref.rs b/tests/ui/explicit_auto_deref.rs index 8f4f35257..deedafad1 100644 --- a/tests/ui/explicit_auto_deref.rs +++ b/tests/ui/explicit_auto_deref.rs @@ -1,5 +1,6 @@ // run-rustfix +#![feature(closure_lifetime_binder)] #![warn(clippy::explicit_auto_deref)] #![allow( dead_code, @@ -67,6 +68,8 @@ fn main() { let s = String::new(); let _: &str = &*s; + let _: &str = &*{ String::new() }; + let _: &str = &mut *{ String::new() }; let _ = &*s; // Don't lint. Inferred type would change. let _: &_ = &*s; // Don't lint. Inferred type would change. @@ -215,4 +218,52 @@ fn main() { let s = &"str"; let _ = || return *s; let _ = || -> &'static str { return *s }; + + struct X; + struct Y(X); + impl core::ops::Deref for Y { + type Target = X; + fn deref(&self) -> &Self::Target { + &self.0 + } + } + let _: &X = &*{ Y(X) }; + let _: &X = &*match 0 { + #[rustfmt::skip] + 0 => { Y(X) }, + _ => panic!(), + }; + let _: &X = &*if true { Y(X) } else { panic!() }; + + fn deref_to_u>(x: &T) -> &U { + &**x + } + + let _ = |x: &'static Box>| -> &'static dyn Iterator { &**x }; + fn ret_any(x: &Box) -> &dyn std::any::Any { + &**x + } + + let x = String::new(); + let _: *const str = &*x; + + struct S7([u32; 1]); + impl core::ops::Deref for S7 { + type Target = [u32; 1]; + fn deref(&self) -> &Self::Target { + &self.0 + } + } + let x = S7([0]); + let _: &[u32] = &*x; + + let c1 = |_: &Vec<&u32>| {}; + let x = &&vec![&1u32]; + c1(*x); + let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<&'b u32> { + if b { + return *x; + } + *x + }; } diff --git a/tests/ui/explicit_auto_deref.stderr b/tests/ui/explicit_auto_deref.stderr index 92765307e..91863abcc 100644 --- a/tests/ui/explicit_auto_deref.stderr +++ b/tests/ui/explicit_auto_deref.stderr @@ -1,202 +1,238 @@ error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:69:20 + --> $DIR/explicit_auto_deref.rs:70:19 | LL | let _: &str = &*s; - | ^^ help: try this: `s` + | ^^^ help: try this: `&s` | = note: `-D clippy::explicit-auto-deref` implied by `-D warnings` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:73:12 + --> $DIR/explicit_auto_deref.rs:71:19 + | +LL | let _: &str = &*{ String::new() }; + | ^^^^^^^^^^^^^^^^^^^ help: try this: `&{ String::new() }` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:72:19 + | +LL | let _: &str = &mut *{ String::new() }; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut { String::new() }` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:76:11 | LL | f_str(&*s); - | ^^ help: try this: `s` + | ^^^ help: try this: `&s` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:77:14 + --> $DIR/explicit_auto_deref.rs:80:13 | LL | f_str_t(&*s, &*s); // Don't lint second param. - | ^^ help: try this: `s` + | ^^^ help: try this: `&s` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:80:25 + --> $DIR/explicit_auto_deref.rs:83:24 | LL | let _: &Box = &**b; - | ^^^ help: try this: `b` + | ^^^^ help: try this: `&b` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:86:8 + --> $DIR/explicit_auto_deref.rs:89:7 | LL | c(&*s); - | ^^ help: try this: `s` + | ^^^ help: try this: `&s` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:92:9 + --> $DIR/explicit_auto_deref.rs:95:9 | LL | &**x | ^^^^ help: try this: `x` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:96:11 + --> $DIR/explicit_auto_deref.rs:99:11 | LL | { &**x } | ^^^^ help: try this: `x` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:100:9 + --> $DIR/explicit_auto_deref.rs:103:9 | LL | &**{ x } | ^^^^^^^^ help: try this: `{ x }` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:104:9 + --> $DIR/explicit_auto_deref.rs:107:9 | LL | &***x | ^^^^^ help: try this: `x` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:121:13 + --> $DIR/explicit_auto_deref.rs:124:12 | LL | f1(&*x); - | ^^ help: try this: `x` + | ^^^ help: try this: `&x` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:122:13 + --> $DIR/explicit_auto_deref.rs:125:12 | LL | f2(&*x); - | ^^ help: try this: `x` + | ^^^ help: try this: `&x` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:123:13 + --> $DIR/explicit_auto_deref.rs:126:12 | LL | f3(&*x); - | ^^ help: try this: `x` + | ^^^ help: try this: `&x` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:124:28 + --> $DIR/explicit_auto_deref.rs:127:27 | LL | f4.callable_str()(&*x); - | ^^ help: try this: `x` + | ^^^ help: try this: `&x` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:125:13 + --> $DIR/explicit_auto_deref.rs:128:12 | LL | f5(&*x); - | ^^ help: try this: `x` + | ^^^ help: try this: `&x` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:126:13 + --> $DIR/explicit_auto_deref.rs:129:12 | LL | f6(&*x); - | ^^ help: try this: `x` + | ^^^ help: try this: `&x` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:127:28 + --> $DIR/explicit_auto_deref.rs:130:27 | LL | f7.callable_str()(&*x); - | ^^ help: try this: `x` + | ^^^ help: try this: `&x` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:128:26 + --> $DIR/explicit_auto_deref.rs:131:25 | LL | f8.callable_t()(&*x); - | ^^ help: try this: `x` + | ^^^ help: try this: `&x` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:129:13 + --> $DIR/explicit_auto_deref.rs:132:12 | LL | f9(&*x); - | ^^ help: try this: `x` + | ^^^ help: try this: `&x` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:130:14 + --> $DIR/explicit_auto_deref.rs:133:13 | LL | f10(&*x); - | ^^ help: try this: `x` + | ^^^ help: try this: `&x` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:131:27 + --> $DIR/explicit_auto_deref.rs:134:26 | LL | f11.callable_t()(&*x); - | ^^ help: try this: `x` + | ^^^ help: try this: `&x` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:135:17 + --> $DIR/explicit_auto_deref.rs:138:16 | LL | let _ = S1(&*s); - | ^^ help: try this: `s` + | ^^^ help: try this: `&s` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:140:22 + --> $DIR/explicit_auto_deref.rs:143:21 | LL | let _ = S2 { s: &*s }; - | ^^ help: try this: `s` + | ^^^ help: try this: `&s` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:156:30 + --> $DIR/explicit_auto_deref.rs:159:30 | LL | let _ = Self::S1(&**s); | ^^^^ help: try this: `s` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:157:35 + --> $DIR/explicit_auto_deref.rs:160:35 | LL | let _ = Self::S2 { s: &**s }; | ^^^^ help: try this: `s` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:160:21 + --> $DIR/explicit_auto_deref.rs:163:20 | LL | let _ = E1::S1(&*s); - | ^^ help: try this: `s` + | ^^^ help: try this: `&s` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:161:26 + --> $DIR/explicit_auto_deref.rs:164:25 | LL | let _ = E1::S2 { s: &*s }; - | ^^ help: try this: `s` + | ^^^ help: try this: `&s` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:179:13 + --> $DIR/explicit_auto_deref.rs:182:13 | LL | let _ = (*b).foo; | ^^^^ help: try this: `b` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:180:13 + --> $DIR/explicit_auto_deref.rs:183:13 | LL | let _ = (**b).foo; | ^^^^^ help: try this: `b` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:195:19 + --> $DIR/explicit_auto_deref.rs:198:19 | LL | let _ = f_str(*ref_str); | ^^^^^^^^ help: try this: `ref_str` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:197:19 + --> $DIR/explicit_auto_deref.rs:200:19 | LL | let _ = f_str(**ref_ref_str); | ^^^^^^^^^^^^^ help: try this: `ref_ref_str` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:207:13 + --> $DIR/explicit_auto_deref.rs:210:13 | LL | f_str(&&*ref_str); // `needless_borrow` will suggest removing both references | ^^^^^^^^ help: try this: `ref_str` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:208:12 + --> $DIR/explicit_auto_deref.rs:211:12 | LL | f_str(&&**ref_str); // `needless_borrow` will suggest removing only one reference | ^^^^^^^^^^ help: try this: `ref_str` error: deref which would be done by auto-deref - --> $DIR/explicit_auto_deref.rs:217:41 + --> $DIR/explicit_auto_deref.rs:220:41 | LL | let _ = || -> &'static str { return *s }; | ^^ help: try this: `s` -error: aborting due to 33 previous errors +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:239:9 + | +LL | &**x + | ^^^^ help: try this: `x` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:262:8 + | +LL | c1(*x); + | ^^ help: try this: `x` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:265:20 + | +LL | return *x; + | ^^ help: try this: `x` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:267:9 + | +LL | *x + | ^^ help: try this: `x` + +error: aborting due to 39 previous errors diff --git a/tests/ui/if_same_then_else.rs b/tests/ui/if_same_then_else.rs index 2598c2ab4..07d2002eb 100644 --- a/tests/ui/if_same_then_else.rs +++ b/tests/ui/if_same_then_else.rs @@ -1,6 +1,6 @@ #![warn(clippy::if_same_then_else)] #![allow( - clippy::blacklisted_name, + clippy::disallowed_names, clippy::eq_op, clippy::never_loop, clippy::no_effect, diff --git a/tests/ui/if_same_then_else2.rs b/tests/ui/if_same_then_else2.rs index 0016009a0..58167f444 100644 --- a/tests/ui/if_same_then_else2.rs +++ b/tests/ui/if_same_then_else2.rs @@ -1,6 +1,6 @@ #![warn(clippy::if_same_then_else)] #![allow( - clippy::blacklisted_name, + clippy::disallowed_names, clippy::collapsible_else_if, clippy::equatable_if_let, clippy::collapsible_if, diff --git a/tests/ui/ifs_same_cond.rs b/tests/ui/ifs_same_cond.rs index 80e9839ff..9850fc091 100644 --- a/tests/ui/ifs_same_cond.rs +++ b/tests/ui/ifs_same_cond.rs @@ -32,9 +32,9 @@ fn ifs_same_cond() { }; let mut v = vec![1]; - if v.pop() == None { + if v.pop().is_none() { // ok, functions - } else if v.pop() == None { + } else if v.pop().is_none() { } if v.len() == 42 { diff --git a/tests/ui/iter_skip_next.fixed b/tests/ui/iter_skip_next.fixed index 2db4c2bee..d56d623b5 100644 --- a/tests/ui/iter_skip_next.fixed +++ b/tests/ui/iter_skip_next.fixed @@ -2,7 +2,7 @@ // aux-build:option_helpers.rs #![warn(clippy::iter_skip_next)] -#![allow(clippy::blacklisted_name)] +#![allow(clippy::disallowed_names)] #![allow(clippy::iter_nth)] #![allow(unused_mut, dead_code)] diff --git a/tests/ui/iter_skip_next.rs b/tests/ui/iter_skip_next.rs index 692edb9ae..3ec5d1b82 100644 --- a/tests/ui/iter_skip_next.rs +++ b/tests/ui/iter_skip_next.rs @@ -2,7 +2,7 @@ // aux-build:option_helpers.rs #![warn(clippy::iter_skip_next)] -#![allow(clippy::blacklisted_name)] +#![allow(clippy::disallowed_names)] #![allow(clippy::iter_nth)] #![allow(unused_mut, dead_code)] diff --git a/tests/ui/let_if_seq.rs b/tests/ui/let_if_seq.rs index c5cb2eb1f..959567f68 100644 --- a/tests/ui/let_if_seq.rs +++ b/tests/ui/let_if_seq.rs @@ -2,7 +2,7 @@ unused_variables, unused_assignments, clippy::similar_names, - clippy::blacklisted_name, + clippy::disallowed_names, clippy::branches_sharing_code, clippy::needless_late_init )] diff --git a/tests/ui/manual_assert.edition2018.fixed b/tests/ui/manual_assert.edition2018.fixed index d0bc640db..65598f1ea 100644 --- a/tests/ui/manual_assert.edition2018.fixed +++ b/tests/ui/manual_assert.edition2018.fixed @@ -17,7 +17,7 @@ fn main() { let c = Some(2); if !a.is_empty() && a.len() == 3 - && c != None + && c.is_some() && !a.is_empty() && a.len() == 3 && !a.is_empty() diff --git a/tests/ui/manual_assert.edition2021.fixed b/tests/ui/manual_assert.edition2021.fixed index d0bc640db..65598f1ea 100644 --- a/tests/ui/manual_assert.edition2021.fixed +++ b/tests/ui/manual_assert.edition2021.fixed @@ -17,7 +17,7 @@ fn main() { let c = Some(2); if !a.is_empty() && a.len() == 3 - && c != None + && c.is_some() && !a.is_empty() && a.len() == 3 && !a.is_empty() diff --git a/tests/ui/manual_assert.fixed b/tests/ui/manual_assert.fixed index 6c2a25c37..a2393674f 100644 --- a/tests/ui/manual_assert.fixed +++ b/tests/ui/manual_assert.fixed @@ -11,7 +11,7 @@ fn main() { let c = Some(2); if !a.is_empty() && a.len() == 3 - && c != None + && c.is_some() && !a.is_empty() && a.len() == 3 && !a.is_empty() diff --git a/tests/ui/manual_assert.rs b/tests/ui/manual_assert.rs index 027747d83..4d2706dd6 100644 --- a/tests/ui/manual_assert.rs +++ b/tests/ui/manual_assert.rs @@ -17,7 +17,7 @@ fn main() { let c = Some(2); if !a.is_empty() && a.len() == 3 - && c != None + && c.is_some() && !a.is_empty() && a.len() == 3 && !a.is_empty() diff --git a/tests/ui/manual_instant_elapsed.fixed b/tests/ui/manual_instant_elapsed.fixed new file mode 100644 index 000000000..0fa776b7b --- /dev/null +++ b/tests/ui/manual_instant_elapsed.fixed @@ -0,0 +1,27 @@ +// run-rustfix +#![warn(clippy::manual_instant_elapsed)] +#![allow(clippy::unnecessary_operation)] +#![allow(unused_variables)] +#![allow(unused_must_use)] + +use std::time::Instant; + +fn main() { + let prev_instant = Instant::now(); + + { + // don't influence + let another_instant = Instant::now(); + } + + let duration = prev_instant.elapsed(); + + // don't catch + let duration = prev_instant.elapsed(); + + Instant::now() - duration; + + let ref_to_instant = &Instant::now(); + + (*ref_to_instant).elapsed(); // to ensure parens are added correctly +} diff --git a/tests/ui/manual_instant_elapsed.rs b/tests/ui/manual_instant_elapsed.rs new file mode 100644 index 000000000..5b11b8453 --- /dev/null +++ b/tests/ui/manual_instant_elapsed.rs @@ -0,0 +1,27 @@ +// run-rustfix +#![warn(clippy::manual_instant_elapsed)] +#![allow(clippy::unnecessary_operation)] +#![allow(unused_variables)] +#![allow(unused_must_use)] + +use std::time::Instant; + +fn main() { + let prev_instant = Instant::now(); + + { + // don't influence + let another_instant = Instant::now(); + } + + let duration = Instant::now() - prev_instant; + + // don't catch + let duration = prev_instant.elapsed(); + + Instant::now() - duration; + + let ref_to_instant = &Instant::now(); + + Instant::now() - *ref_to_instant; // to ensure parens are added correctly +} diff --git a/tests/ui/manual_instant_elapsed.stderr b/tests/ui/manual_instant_elapsed.stderr new file mode 100644 index 000000000..5537f5642 --- /dev/null +++ b/tests/ui/manual_instant_elapsed.stderr @@ -0,0 +1,16 @@ +error: manual implementation of `Instant::elapsed` + --> $DIR/manual_instant_elapsed.rs:17:20 + | +LL | let duration = Instant::now() - prev_instant; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `prev_instant.elapsed()` + | + = note: `-D clippy::manual-instant-elapsed` implied by `-D warnings` + +error: manual implementation of `Instant::elapsed` + --> $DIR/manual_instant_elapsed.rs:26:5 + | +LL | Instant::now() - *ref_to_instant; // to ensure parens are added correctly + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*ref_to_instant).elapsed()` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/manual_ok_or.fixed b/tests/ui/manual_ok_or.fixed index 887a97d7a..d864f8554 100644 --- a/tests/ui/manual_ok_or.fixed +++ b/tests/ui/manual_ok_or.fixed @@ -1,6 +1,6 @@ // run-rustfix #![warn(clippy::manual_ok_or)] -#![allow(clippy::blacklisted_name)] +#![allow(clippy::disallowed_names)] #![allow(clippy::redundant_closure)] #![allow(dead_code)] #![allow(unused_must_use)] diff --git a/tests/ui/manual_ok_or.rs b/tests/ui/manual_ok_or.rs index 3c99872f5..626476846 100644 --- a/tests/ui/manual_ok_or.rs +++ b/tests/ui/manual_ok_or.rs @@ -1,6 +1,6 @@ // run-rustfix #![warn(clippy::manual_ok_or)] -#![allow(clippy::blacklisted_name)] +#![allow(clippy::disallowed_names)] #![allow(clippy::redundant_closure)] #![allow(dead_code)] #![allow(unused_must_use)] diff --git a/tests/ui/match_same_arms2.rs b/tests/ui/match_same_arms2.rs index 7aba5b447..61793e80c 100644 --- a/tests/ui/match_same_arms2.rs +++ b/tests/ui/match_same_arms2.rs @@ -1,5 +1,5 @@ #![warn(clippy::match_same_arms)] -#![allow(clippy::blacklisted_name, clippy::diverging_sub_expression)] +#![allow(clippy::disallowed_names, clippy::diverging_sub_expression)] fn bar(_: T) {} fn foo() -> bool { diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 1970c2eae..6f22366ea 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -2,7 +2,7 @@ #![warn(clippy::all, clippy::pedantic)] #![allow( - clippy::blacklisted_name, + clippy::disallowed_names, clippy::default_trait_access, clippy::missing_docs_in_private_items, clippy::missing_safety_doc, diff --git a/tests/ui/mismatching_type_param_order.rs b/tests/ui/mismatching_type_param_order.rs index 8c0da84d8..40c1fcae1 100644 --- a/tests/ui/mismatching_type_param_order.rs +++ b/tests/ui/mismatching_type_param_order.rs @@ -1,5 +1,5 @@ #![warn(clippy::mismatching_type_param_order)] -#![allow(clippy::blacklisted_name)] +#![allow(clippy::disallowed_names)] fn main() { struct Foo { 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 aa60d0504..b950248ef 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -3,12 +3,16 @@ //! The .stderr output of this test should be empty. Otherwise it's a bug somewhere. // aux-build:helper.rs +// aux-build:../../auxiliary/proc_macro_with_span.rs #![warn(clippy::missing_const_for_fn)] #![feature(start)] #![feature(custom_inner_attributes)] extern crate helper; +extern crate proc_macro_with_span; + +use proc_macro_with_span::with_span; struct Game; @@ -119,3 +123,8 @@ mod const_fn_stabilized_after_msrv { byte.is_ascii_digit(); } } + +with_span! { + span + fn dont_check_in_proc_macro() {} +} diff --git a/tests/ui/missing-doc.rs b/tests/ui/missing_doc.rs similarity index 82% rename from tests/ui/missing-doc.rs rename to tests/ui/missing_doc.rs index 6e2e710e2..29cc026a8 100644 --- a/tests/ui/missing-doc.rs +++ b/tests/ui/missing_doc.rs @@ -1,3 +1,5 @@ +// aux-build: proc_macro_with_span.rs + #![warn(clippy::missing_docs_in_private_items)] // When denying at the crate level, be sure to not get random warnings from the // injected intrinsics by the compiler. @@ -5,6 +7,9 @@ //! Some garbage docs for the crate here #![doc = "More garbage"] +extern crate proc_macro_with_span; + +use proc_macro_with_span::with_span; use std::arch::global_asm; type Typedef = String; @@ -100,3 +105,11 @@ fn main() {} // Ensure global asm doesn't require documentation. global_asm! { "" } + +// Don't lint proc macro output with an unexpected span. +with_span!(span pub struct FooPm { pub field: u32}); +with_span!(span pub struct FooPm2;); +with_span!(span pub enum FooPm3 { A, B(u32), C { field: u32 }}); +with_span!(span pub fn foo_pm() {}); +with_span!(span pub static FOO_PM: u32 = 0;); +with_span!(span pub const FOO2_PM: u32 = 0;); diff --git a/tests/ui/missing-doc.stderr b/tests/ui/missing_doc.stderr similarity index 79% rename from tests/ui/missing-doc.stderr rename to tests/ui/missing_doc.stderr index a876dc078..6c8e66f46 100644 --- a/tests/ui/missing-doc.stderr +++ b/tests/ui/missing_doc.stderr @@ -1,5 +1,5 @@ error: missing documentation for a type alias - --> $DIR/missing-doc.rs:10:1 + --> $DIR/missing_doc.rs:15:1 | LL | type Typedef = String; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -7,37 +7,37 @@ LL | type Typedef = String; = note: `-D clippy::missing-docs-in-private-items` implied by `-D warnings` error: missing documentation for a type alias - --> $DIR/missing-doc.rs:11:1 + --> $DIR/missing_doc.rs:16:1 | LL | pub type PubTypedef = String; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a module - --> $DIR/missing-doc.rs:13:1 + --> $DIR/missing_doc.rs:18:1 | LL | mod module_no_dox {} | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a module - --> $DIR/missing-doc.rs:14:1 + --> $DIR/missing_doc.rs:19:1 | LL | pub mod pub_module_no_dox {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:18:1 + --> $DIR/missing_doc.rs:23:1 | LL | pub fn foo2() {} | ^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:19:1 + --> $DIR/missing_doc.rs:24:1 | LL | fn foo3() {} | ^^^^^^^^^^^^ error: missing documentation for an enum - --> $DIR/missing-doc.rs:33:1 + --> $DIR/missing_doc.rs:38:1 | LL | / enum Baz { LL | | BazA { a: isize, b: isize }, @@ -46,31 +46,31 @@ LL | | } | |_^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:34:5 + --> $DIR/missing_doc.rs:39:5 | LL | BazA { a: isize, b: isize }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:34:12 + --> $DIR/missing_doc.rs:39:12 | LL | BazA { a: isize, b: isize }, | ^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:34:22 + --> $DIR/missing_doc.rs:39:22 | LL | BazA { a: isize, b: isize }, | ^^^^^^^^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:35:5 + --> $DIR/missing_doc.rs:40:5 | LL | BarB, | ^^^^ error: missing documentation for an enum - --> $DIR/missing-doc.rs:38:1 + --> $DIR/missing_doc.rs:43:1 | LL | / pub enum PubBaz { LL | | PubBazA { a: isize }, @@ -78,43 +78,43 @@ LL | | } | |_^ error: missing documentation for a variant - --> $DIR/missing-doc.rs:39:5 + --> $DIR/missing_doc.rs:44:5 | LL | PubBazA { a: isize }, | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc.rs:39:15 + --> $DIR/missing_doc.rs:44:15 | LL | PubBazA { a: isize }, | ^^^^^^^^ error: missing documentation for a constant - --> $DIR/missing-doc.rs:59:1 + --> $DIR/missing_doc.rs:64:1 | LL | const FOO: u32 = 0; | ^^^^^^^^^^^^^^^^^^^ error: missing documentation for a constant - --> $DIR/missing-doc.rs:66:1 + --> $DIR/missing_doc.rs:71:1 | LL | pub const FOO4: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a static - --> $DIR/missing-doc.rs:68:1 + --> $DIR/missing_doc.rs:73:1 | LL | static BAR: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a static - --> $DIR/missing-doc.rs:75:1 + --> $DIR/missing_doc.rs:80:1 | LL | pub static BAR4: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a module - --> $DIR/missing-doc.rs:77:1 + --> $DIR/missing_doc.rs:82:1 | LL | / mod internal_impl { LL | | /// dox @@ -126,31 +126,31 @@ LL | | } | |_^ error: missing documentation for a function - --> $DIR/missing-doc.rs:80:5 + --> $DIR/missing_doc.rs:85:5 | LL | pub fn undocumented1() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:81:5 + --> $DIR/missing_doc.rs:86:5 | LL | pub fn undocumented2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:82:5 + --> $DIR/missing_doc.rs:87:5 | LL | fn undocumented3() {} | ^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:87:9 + --> $DIR/missing_doc.rs:92:9 | LL | pub fn also_undocumented1() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/missing-doc.rs:88:9 + --> $DIR/missing_doc.rs:93:9 | LL | fn also_undocumented2() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/missing-doc-crate.rs b/tests/ui/missing_doc_crate.rs similarity index 100% rename from tests/ui/missing-doc-crate.rs rename to tests/ui/missing_doc_crate.rs diff --git a/tests/ui/missing-doc-crate-missing.rs b/tests/ui/missing_doc_crate_missing.rs similarity index 100% rename from tests/ui/missing-doc-crate-missing.rs rename to tests/ui/missing_doc_crate_missing.rs diff --git a/tests/ui/missing-doc-crate-missing.stderr b/tests/ui/missing_doc_crate_missing.stderr similarity index 86% rename from tests/ui/missing-doc-crate-missing.stderr rename to tests/ui/missing_doc_crate_missing.stderr index d56c5cc4c..19516bf5f 100644 --- a/tests/ui/missing-doc-crate-missing.stderr +++ b/tests/ui/missing_doc_crate_missing.stderr @@ -1,5 +1,5 @@ error: missing documentation for the crate - --> $DIR/missing-doc-crate-missing.rs:1:1 + --> $DIR/missing_doc_crate_missing.rs:1:1 | LL | / #![warn(clippy::missing_docs_in_private_items)] LL | | diff --git a/tests/ui/missing-doc-impl.rs b/tests/ui/missing_doc_impl.rs similarity index 83% rename from tests/ui/missing-doc-impl.rs rename to tests/ui/missing_doc_impl.rs index d5724bf66..0396d1193 100644 --- a/tests/ui/missing-doc-impl.rs +++ b/tests/ui/missing_doc_impl.rs @@ -1,3 +1,5 @@ +// aux-build: proc_macro_with_span.rs + #![warn(clippy::missing_docs_in_private_items)] #![allow(dead_code)] #![feature(associated_type_defaults)] @@ -5,6 +7,9 @@ //! Some garbage docs for the crate here #![doc = "More garbage"] +extern crate proc_macro_with_span; +use proc_macro_with_span::with_span; + struct Foo { a: isize, b: isize, @@ -90,3 +95,13 @@ impl F for Foo { } fn main() {} + +// don't lint proc macro output +with_span!(span + pub struct FooPm; + impl FooPm { + pub fn foo() {} + pub const fn bar() {} + pub const X: u32 = 0; + } +); diff --git a/tests/ui/missing-doc-impl.stderr b/tests/ui/missing_doc_impl.stderr similarity index 78% rename from tests/ui/missing-doc-impl.stderr rename to tests/ui/missing_doc_impl.stderr index bda63d66a..f22fa19db 100644 --- a/tests/ui/missing-doc-impl.stderr +++ b/tests/ui/missing_doc_impl.stderr @@ -1,5 +1,5 @@ error: missing documentation for a struct - --> $DIR/missing-doc-impl.rs:8:1 + --> $DIR/missing_doc_impl.rs:13:1 | LL | / struct Foo { LL | | a: isize, @@ -10,19 +10,19 @@ LL | | } = note: `-D clippy::missing-docs-in-private-items` implied by `-D warnings` error: missing documentation for a struct field - --> $DIR/missing-doc-impl.rs:9:5 + --> $DIR/missing_doc_impl.rs:14:5 | LL | a: isize, | ^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc-impl.rs:10:5 + --> $DIR/missing_doc_impl.rs:15:5 | LL | b: isize, | ^^^^^^^^ error: missing documentation for a struct - --> $DIR/missing-doc-impl.rs:13:1 + --> $DIR/missing_doc_impl.rs:18:1 | LL | / pub struct PubFoo { LL | | pub a: isize, @@ -31,19 +31,19 @@ LL | | } | |_^ error: missing documentation for a struct field - --> $DIR/missing-doc-impl.rs:14:5 + --> $DIR/missing_doc_impl.rs:19:5 | LL | pub a: isize, | ^^^^^^^^^^^^ error: missing documentation for a struct field - --> $DIR/missing-doc-impl.rs:15:5 + --> $DIR/missing_doc_impl.rs:20:5 | LL | b: isize, | ^^^^^^^^ error: missing documentation for a trait - --> $DIR/missing-doc-impl.rs:38:1 + --> $DIR/missing_doc_impl.rs:43:1 | LL | / pub trait C { LL | | fn foo(&self); @@ -52,31 +52,31 @@ LL | | } | |_^ error: missing documentation for an associated function - --> $DIR/missing-doc-impl.rs:39:5 + --> $DIR/missing_doc_impl.rs:44:5 | LL | fn foo(&self); | ^^^^^^^^^^^^^^ error: missing documentation for an associated function - --> $DIR/missing-doc-impl.rs:40:5 + --> $DIR/missing_doc_impl.rs:45:5 | LL | fn foo_with_impl(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for an associated type - --> $DIR/missing-doc-impl.rs:50:5 + --> $DIR/missing_doc_impl.rs:55:5 | LL | type AssociatedType; | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for an associated type - --> $DIR/missing-doc-impl.rs:51:5 + --> $DIR/missing_doc_impl.rs:56:5 | LL | type AssociatedTypeDef = Self; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing documentation for an associated function - --> $DIR/missing-doc-impl.rs:62:5 + --> $DIR/missing_doc_impl.rs:67:5 | LL | / pub fn new() -> Self { LL | | Foo { a: 0, b: 0 } @@ -84,19 +84,19 @@ LL | | } | |_____^ error: missing documentation for an associated function - --> $DIR/missing-doc-impl.rs:65:5 + --> $DIR/missing_doc_impl.rs:70:5 | LL | fn bar() {} | ^^^^^^^^^^^ error: missing documentation for an associated function - --> $DIR/missing-doc-impl.rs:69:5 + --> $DIR/missing_doc_impl.rs:74:5 | LL | pub fn foo() {} | ^^^^^^^^^^^^^^^ error: missing documentation for an associated function - --> $DIR/missing-doc-impl.rs:73:5 + --> $DIR/missing_doc_impl.rs:78:5 | LL | / fn foo2() -> u32 { LL | | 1 diff --git a/tests/ui/mistyped_literal_suffix.fixed b/tests/ui/mistyped_literal_suffix.fixed index a7b36d53c..becb9562a 100644 --- a/tests/ui/mistyped_literal_suffix.fixed +++ b/tests/ui/mistyped_literal_suffix.fixed @@ -1,4 +1,5 @@ // run-rustfix +// aux-build: proc_macro_with_span.rs #![allow( dead_code, @@ -9,6 +10,9 @@ clippy::unusual_byte_groupings )] +extern crate proc_macro_with_span; +use proc_macro_with_span::with_span; + fn main() { let fail14 = 2_i32; let fail15 = 4_i64; @@ -40,4 +44,6 @@ fn main() { let ok38 = 124_64.0; let _ = 1.123_45E1_f32; + + let _ = with_span!(1 2_u32); } diff --git a/tests/ui/mistyped_literal_suffix.rs b/tests/ui/mistyped_literal_suffix.rs index c97b31965..ee841bcd7 100644 --- a/tests/ui/mistyped_literal_suffix.rs +++ b/tests/ui/mistyped_literal_suffix.rs @@ -1,4 +1,5 @@ // run-rustfix +// aux-build: proc_macro_with_span.rs #![allow( dead_code, @@ -9,6 +10,9 @@ clippy::unusual_byte_groupings )] +extern crate proc_macro_with_span; +use proc_macro_with_span::with_span; + fn main() { let fail14 = 2_32; let fail15 = 4_64; @@ -40,4 +44,6 @@ fn main() { let ok38 = 124_64.0; let _ = 1.12345E1_32; + + let _ = with_span!(1 2_u32); } diff --git a/tests/ui/mistyped_literal_suffix.stderr b/tests/ui/mistyped_literal_suffix.stderr index fb761d9bd..ef8e6a33d 100644 --- a/tests/ui/mistyped_literal_suffix.stderr +++ b/tests/ui/mistyped_literal_suffix.stderr @@ -1,5 +1,5 @@ error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:13:18 + --> $DIR/mistyped_literal_suffix.rs:17:18 | LL | let fail14 = 2_32; | ^^^^ help: did you mean to write: `2_i32` @@ -7,91 +7,91 @@ LL | let fail14 = 2_32; = note: `#[deny(clippy::mistyped_literal_suffixes)]` on by default error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:14:18 + --> $DIR/mistyped_literal_suffix.rs:18:18 | LL | let fail15 = 4_64; | ^^^^ help: did you mean to write: `4_i64` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:15:18 + --> $DIR/mistyped_literal_suffix.rs:19:18 | LL | let fail16 = 7_8; // | ^^^ help: did you mean to write: `7_i8` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:16:18 + --> $DIR/mistyped_literal_suffix.rs:20:18 | LL | let fail17 = 23_16; // | ^^^^^ help: did you mean to write: `23_i16` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:19:18 + --> $DIR/mistyped_literal_suffix.rs:23:18 | LL | let fail20 = 2__8; // | ^^^^ help: did you mean to write: `2_i8` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:20:18 + --> $DIR/mistyped_literal_suffix.rs:24:18 | LL | let fail21 = 4___16; // | ^^^^^^ help: did you mean to write: `4_i16` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:23:18 + --> $DIR/mistyped_literal_suffix.rs:27:18 | LL | let fail25 = 1E2_32; | ^^^^^^ help: did you mean to write: `1E2_f32` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:24:18 + --> $DIR/mistyped_literal_suffix.rs:28:18 | LL | let fail26 = 43E7_64; | ^^^^^^^ help: did you mean to write: `43E7_f64` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:25:18 + --> $DIR/mistyped_literal_suffix.rs:29:18 | LL | let fail27 = 243E17_32; | ^^^^^^^^^ help: did you mean to write: `243E17_f32` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:26:18 + --> $DIR/mistyped_literal_suffix.rs:30:18 | LL | let fail28 = 241251235E723_64; | ^^^^^^^^^^^^^^^^ help: did you mean to write: `241_251_235E723_f64` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:30:18 + --> $DIR/mistyped_literal_suffix.rs:34:18 | LL | let fail30 = 127_8; // should be i8 | ^^^^^ help: did you mean to write: `127_i8` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:31:18 + --> $DIR/mistyped_literal_suffix.rs:35:18 | LL | let fail31 = 240_8; // should be u8 | ^^^^^ help: did you mean to write: `240_u8` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:33:18 + --> $DIR/mistyped_literal_suffix.rs:37:18 | LL | let fail33 = 0x1234_16; | ^^^^^^^^^ help: did you mean to write: `0x1234_i16` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:34:18 + --> $DIR/mistyped_literal_suffix.rs:38:18 | LL | let fail34 = 0xABCD_16; | ^^^^^^^^^ help: did you mean to write: `0xABCD_u16` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:36:18 + --> $DIR/mistyped_literal_suffix.rs:40:18 | LL | let fail36 = 0xFFFF_FFFF_FFFF_FFFF_64; // u64 | ^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean to write: `0xFFFF_FFFF_FFFF_FFFF_u64` error: mistyped literal suffix - --> $DIR/mistyped_literal_suffix.rs:42:13 + --> $DIR/mistyped_literal_suffix.rs:46:13 | LL | let _ = 1.12345E1_32; | ^^^^^^^^^^^^ help: did you mean to write: `1.123_45E1_f32` diff --git a/tests/ui/mixed_read_write_in_expression.rs b/tests/ui/mixed_read_write_in_expression.rs index 7640057ab..6efc7657e 100644 --- a/tests/ui/mixed_read_write_in_expression.rs +++ b/tests/ui/mixed_read_write_in_expression.rs @@ -4,7 +4,7 @@ unused_variables, clippy::no_effect, dead_code, - clippy::blacklisted_name + clippy::disallowed_names )] fn main() { let mut x = 0; diff --git a/tests/ui/op_ref.rs b/tests/ui/op_ref.rs index d8bf66603..07226b0a1 100644 --- a/tests/ui/op_ref.rs +++ b/tests/ui/op_ref.rs @@ -1,4 +1,4 @@ -#![allow(unused_variables, clippy::blacklisted_name)] +#![allow(unused_variables, clippy::disallowed_names)] #![warn(clippy::op_ref)] use std::collections::HashSet; use std::ops::{BitAnd, Mul}; diff --git a/tests/ui/logic_bug.rs b/tests/ui/overly_complex_bool_expr.rs similarity index 90% rename from tests/ui/logic_bug.rs rename to tests/ui/overly_complex_bool_expr.rs index dd6b1db5f..04a30a832 100644 --- a/tests/ui/logic_bug.rs +++ b/tests/ui/overly_complex_bool_expr.rs @@ -1,6 +1,6 @@ #![feature(lint_reasons)] #![allow(unused, clippy::diverging_sub_expression)] -#![warn(clippy::logic_bug)] +#![warn(clippy::overly_complex_bool_expr)] fn main() { let a: bool = unimplemented!(); @@ -29,6 +29,6 @@ fn equality_stuff() { fn check_expect() { let a: i32 = unimplemented!(); let b: i32 = unimplemented!(); - #[expect(clippy::logic_bug)] + #[expect(clippy::overly_complex_bool_expr)] let _ = a < b && a >= b; } diff --git a/tests/ui/logic_bug.stderr b/tests/ui/overly_complex_bool_expr.stderr similarity index 76% rename from tests/ui/logic_bug.stderr rename to tests/ui/overly_complex_bool_expr.stderr index 4021fbf45..158cae8b8 100644 --- a/tests/ui/logic_bug.stderr +++ b/tests/ui/overly_complex_bool_expr.stderr @@ -1,60 +1,60 @@ error: this boolean expression contains a logic bug - --> $DIR/logic_bug.rs:11:13 + --> $DIR/overly_complex_bool_expr.rs:11:13 | LL | let _ = a && b || a; | ^^^^^^^^^^^ help: it would look like the following: `a` | - = note: `-D clippy::logic-bug` implied by `-D warnings` + = note: `-D clippy::overly-complex-bool-expr` implied by `-D warnings` help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/logic_bug.rs:11:18 + --> $DIR/overly_complex_bool_expr.rs:11:18 | LL | let _ = a && b || a; | ^ error: this boolean expression contains a logic bug - --> $DIR/logic_bug.rs:13:13 + --> $DIR/overly_complex_bool_expr.rs:13:13 | LL | let _ = false && a; | ^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/logic_bug.rs:13:22 + --> $DIR/overly_complex_bool_expr.rs:13:22 | LL | let _ = false && a; | ^ error: this boolean expression contains a logic bug - --> $DIR/logic_bug.rs:23:13 + --> $DIR/overly_complex_bool_expr.rs:23:13 | LL | let _ = a == b && a != b; | ^^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/logic_bug.rs:23:13 + --> $DIR/overly_complex_bool_expr.rs:23:13 | LL | let _ = a == b && a != b; | ^^^^^^ error: this boolean expression contains a logic bug - --> $DIR/logic_bug.rs:24:13 + --> $DIR/overly_complex_bool_expr.rs:24:13 | LL | let _ = a < b && a >= b; | ^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/logic_bug.rs:24:13 + --> $DIR/overly_complex_bool_expr.rs:24:13 | LL | let _ = a < b && a >= b; | ^^^^^ error: this boolean expression contains a logic bug - --> $DIR/logic_bug.rs:25:13 + --> $DIR/overly_complex_bool_expr.rs:25:13 | LL | let _ = a > b && a <= b; | ^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> $DIR/logic_bug.rs:25:13 + --> $DIR/overly_complex_bool_expr.rs:25:13 | LL | let _ = a > b && a <= b; | ^^^^^ diff --git a/tests/ui/partialeq_to_none.fixed b/tests/ui/partialeq_to_none.fixed new file mode 100644 index 000000000..f3e4c58d6 --- /dev/null +++ b/tests/ui/partialeq_to_none.fixed @@ -0,0 +1,62 @@ +// run-rustfix +#![warn(clippy::partialeq_to_none)] + +struct Foobar; + +impl PartialEq> for Foobar { + fn eq(&self, _: &Option<()>) -> bool { + false + } +} + +#[allow(dead_code)] +fn foo(f: Option) -> &'static str { + if f.is_some() { "yay" } else { "nay" } +} + +fn foobar() -> Option<()> { + None +} + +fn bar() -> Result<(), ()> { + Ok(()) +} + +fn optref() -> &'static &'static Option<()> { + &&None +} + +fn main() { + let x = Some(0); + + let _ = x.is_none(); + let _ = x.is_some(); + let _ = x.is_none(); + let _ = x.is_some(); + + if foobar().is_none() {} + + if bar().ok().is_some() {} + + let _ = Some(1 + 2).is_some(); + + let _ = { Some(0) }.is_none(); + + let _ = { + /* + This comment runs long + */ + Some(1) + }.is_some(); + + // Should not trigger, as `Foobar` is not an `Option` and has no `is_none` + let _ = Foobar == None; + + let _ = optref().is_none(); + let _ = optref().is_some(); + let _ = optref().is_none(); + let _ = optref().is_some(); + + let x = Box::new(Option::<()>::None); + let _ = (*x).is_some(); +} diff --git a/tests/ui/partialeq_to_none.rs b/tests/ui/partialeq_to_none.rs new file mode 100644 index 000000000..767b2a38b --- /dev/null +++ b/tests/ui/partialeq_to_none.rs @@ -0,0 +1,62 @@ +// run-rustfix +#![warn(clippy::partialeq_to_none)] + +struct Foobar; + +impl PartialEq> for Foobar { + fn eq(&self, _: &Option<()>) -> bool { + false + } +} + +#[allow(dead_code)] +fn foo(f: Option) -> &'static str { + if f != None { "yay" } else { "nay" } +} + +fn foobar() -> Option<()> { + None +} + +fn bar() -> Result<(), ()> { + Ok(()) +} + +fn optref() -> &'static &'static Option<()> { + &&None +} + +fn main() { + let x = Some(0); + + let _ = x == None; + let _ = x != None; + let _ = None == x; + let _ = None != x; + + if foobar() == None {} + + if bar().ok() != None {} + + let _ = Some(1 + 2) != None; + + let _ = { Some(0) } == None; + + let _ = { + /* + This comment runs long + */ + Some(1) + } != None; + + // Should not trigger, as `Foobar` is not an `Option` and has no `is_none` + let _ = Foobar == None; + + let _ = optref() == &&None; + let _ = &&None != optref(); + let _ = **optref() == None; + let _ = &None != *optref(); + + let x = Box::new(Option::<()>::None); + let _ = None != *x; +} diff --git a/tests/ui/partialeq_to_none.stderr b/tests/ui/partialeq_to_none.stderr new file mode 100644 index 000000000..de15a9f7b --- /dev/null +++ b/tests/ui/partialeq_to_none.stderr @@ -0,0 +1,110 @@ +error: binary comparison to literal `Option::None` + --> $DIR/partialeq_to_none.rs:14:8 + | +LL | if f != None { "yay" } else { "nay" } + | ^^^^^^^^^ help: use `Option::is_some()` instead: `f.is_some()` + | + = note: `-D clippy::partialeq-to-none` implied by `-D warnings` + +error: binary comparison to literal `Option::None` + --> $DIR/partialeq_to_none.rs:32:13 + | +LL | let _ = x == None; + | ^^^^^^^^^ help: use `Option::is_none()` instead: `x.is_none()` + +error: binary comparison to literal `Option::None` + --> $DIR/partialeq_to_none.rs:33:13 + | +LL | let _ = x != None; + | ^^^^^^^^^ help: use `Option::is_some()` instead: `x.is_some()` + +error: binary comparison to literal `Option::None` + --> $DIR/partialeq_to_none.rs:34:13 + | +LL | let _ = None == x; + | ^^^^^^^^^ help: use `Option::is_none()` instead: `x.is_none()` + +error: binary comparison to literal `Option::None` + --> $DIR/partialeq_to_none.rs:35:13 + | +LL | let _ = None != x; + | ^^^^^^^^^ help: use `Option::is_some()` instead: `x.is_some()` + +error: binary comparison to literal `Option::None` + --> $DIR/partialeq_to_none.rs:37:8 + | +LL | if foobar() == None {} + | ^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `foobar().is_none()` + +error: binary comparison to literal `Option::None` + --> $DIR/partialeq_to_none.rs:39:8 + | +LL | if bar().ok() != None {} + | ^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `bar().ok().is_some()` + +error: binary comparison to literal `Option::None` + --> $DIR/partialeq_to_none.rs:41:13 + | +LL | let _ = Some(1 + 2) != None; + | ^^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `Some(1 + 2).is_some()` + +error: binary comparison to literal `Option::None` + --> $DIR/partialeq_to_none.rs:43:13 + | +LL | let _ = { Some(0) } == None; + | ^^^^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `{ Some(0) }.is_none()` + +error: binary comparison to literal `Option::None` + --> $DIR/partialeq_to_none.rs:45:13 + | +LL | let _ = { + | _____________^ +LL | | /* +LL | | This comment runs long +LL | | */ +LL | | Some(1) +LL | | } != None; + | |_____________^ + | +help: use `Option::is_some()` instead + | +LL ~ let _ = { +LL + /* +LL + This comment runs long +LL + */ +LL + Some(1) +LL ~ }.is_some(); + | + +error: binary comparison to literal `Option::None` + --> $DIR/partialeq_to_none.rs:55:13 + | +LL | let _ = optref() == &&None; + | ^^^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `optref().is_none()` + +error: binary comparison to literal `Option::None` + --> $DIR/partialeq_to_none.rs:56:13 + | +LL | let _ = &&None != optref(); + | ^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `optref().is_some()` + +error: binary comparison to literal `Option::None` + --> $DIR/partialeq_to_none.rs:57:13 + | +LL | let _ = **optref() == None; + | ^^^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `optref().is_none()` + +error: binary comparison to literal `Option::None` + --> $DIR/partialeq_to_none.rs:58:13 + | +LL | let _ = &None != *optref(); + | ^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `optref().is_some()` + +error: binary comparison to literal `Option::None` + --> $DIR/partialeq_to_none.rs:61:13 + | +LL | let _ = None != *x; + | ^^^^^^^^^^ help: use `Option::is_some()` instead: `(*x).is_some()` + +error: aborting due to 15 previous errors + diff --git a/tests/ui/rc_mutex.rs b/tests/ui/rc_mutex.rs index 18e8a2e01..432972bbc 100644 --- a/tests/ui/rc_mutex.rs +++ b/tests/ui/rc_mutex.rs @@ -1,5 +1,5 @@ #![warn(clippy::rc_mutex)] -#![allow(unused, clippy::blacklisted_name)] +#![allow(unused, clippy::disallowed_names)] use std::rc::Rc; use std::sync::Mutex; diff --git a/tests/ui/redundant_allocation.rs b/tests/ui/redundant_allocation.rs index cf7d8c6e3..574d34aed 100644 --- a/tests/ui/redundant_allocation.rs +++ b/tests/ui/redundant_allocation.rs @@ -1,7 +1,5 @@ #![warn(clippy::all)] -#![allow(clippy::boxed_local, clippy::needless_pass_by_value)] -#![allow(clippy::blacklisted_name, unused_variables, dead_code)] -#![allow(unused_imports)] +#![allow(clippy::boxed_local, clippy::disallowed_names)] pub struct MyStruct; @@ -9,13 +7,7 @@ pub struct SubT { foo: T, } -pub enum MyEnum { - One, - Two, -} - mod outer_box { - use crate::MyEnum; use crate::MyStruct; use crate::SubT; use std::boxed::Box; @@ -36,7 +28,6 @@ mod outer_box { } mod outer_rc { - use crate::MyEnum; use crate::MyStruct; use crate::SubT; use std::boxed::Box; @@ -57,7 +48,6 @@ mod outer_rc { } mod outer_arc { - use crate::MyEnum; use crate::MyStruct; use crate::SubT; use std::boxed::Box; diff --git a/tests/ui/redundant_allocation.stderr b/tests/ui/redundant_allocation.stderr index fab1b069f..54d4d88db 100644 --- a/tests/ui/redundant_allocation.stderr +++ b/tests/ui/redundant_allocation.stderr @@ -1,5 +1,5 @@ error: usage of `Box>` - --> $DIR/redundant_allocation.rs:25:30 + --> $DIR/redundant_allocation.rs:17:30 | LL | pub fn box_test6(foo: Box>) {} | ^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | pub fn box_test6(foo: Box>) {} = help: consider using just `Box` or `Rc` error: usage of `Box>` - --> $DIR/redundant_allocation.rs:27:30 + --> $DIR/redundant_allocation.rs:19:30 | LL | pub fn box_test7(foo: Box>) {} | ^^^^^^^^^^^ @@ -18,7 +18,7 @@ LL | pub fn box_test7(foo: Box>) {} = help: consider using just `Box` or `Arc` error: usage of `Box>>` - --> $DIR/redundant_allocation.rs:29:27 + --> $DIR/redundant_allocation.rs:21:27 | LL | pub fn box_test8() -> Box>> { | ^^^^^^^^^^^^^^^^^^^^ @@ -27,7 +27,7 @@ LL | pub fn box_test8() -> Box>> { = help: consider using just `Box>` or `Rc>` error: usage of `Box>` - --> $DIR/redundant_allocation.rs:33:30 + --> $DIR/redundant_allocation.rs:25:30 | LL | pub fn box_test9(foo: Box>) -> Box>> { | ^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL | pub fn box_test9(foo: Box>) -> Box>> { = help: consider using just `Box` or `Arc` error: usage of `Box>>` - --> $DIR/redundant_allocation.rs:33:46 + --> $DIR/redundant_allocation.rs:25:46 | LL | pub fn box_test9(foo: Box>) -> Box>> { | ^^^^^^^^^^^^^^^^^ @@ -45,7 +45,7 @@ LL | pub fn box_test9(foo: Box>) -> Box>> { = help: consider using just `Box>` or `Arc>` error: usage of `Rc>` - --> $DIR/redundant_allocation.rs:46:24 + --> $DIR/redundant_allocation.rs:37:24 | LL | pub fn rc_test5(a: Rc>) {} | ^^^^^^^^^^^^^ @@ -54,7 +54,7 @@ LL | pub fn rc_test5(a: Rc>) {} = help: consider using just `Rc` or `Box` error: usage of `Rc>` - --> $DIR/redundant_allocation.rs:48:24 + --> $DIR/redundant_allocation.rs:39:24 | LL | pub fn rc_test7(a: Rc>) {} | ^^^^^^^^^^^^^ @@ -63,7 +63,7 @@ LL | pub fn rc_test7(a: Rc>) {} = help: consider using just `Rc` or `Arc` error: usage of `Rc>>` - --> $DIR/redundant_allocation.rs:50:26 + --> $DIR/redundant_allocation.rs:41:26 | LL | pub fn rc_test8() -> Rc>> { | ^^^^^^^^^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | pub fn rc_test8() -> Rc>> { = help: consider using just `Rc>` or `Box>` error: usage of `Rc>` - --> $DIR/redundant_allocation.rs:54:29 + --> $DIR/redundant_allocation.rs:45:29 | LL | pub fn rc_test9(foo: Rc>) -> Rc>> { | ^^^^^^^^^^ @@ -81,7 +81,7 @@ LL | pub fn rc_test9(foo: Rc>) -> Rc>> { = help: consider using just `Rc` or `Arc` error: usage of `Rc>>` - --> $DIR/redundant_allocation.rs:54:44 + --> $DIR/redundant_allocation.rs:45:44 | LL | pub fn rc_test9(foo: Rc>) -> Rc>> { | ^^^^^^^^^^^^^^^^ @@ -90,7 +90,7 @@ LL | pub fn rc_test9(foo: Rc>) -> Rc>> { = help: consider using just `Rc>` or `Arc>` error: usage of `Arc>` - --> $DIR/redundant_allocation.rs:67:25 + --> $DIR/redundant_allocation.rs:57:25 | LL | pub fn arc_test5(a: Arc>) {} | ^^^^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL | pub fn arc_test5(a: Arc>) {} = help: consider using just `Arc` or `Box` error: usage of `Arc>` - --> $DIR/redundant_allocation.rs:69:25 + --> $DIR/redundant_allocation.rs:59:25 | LL | pub fn arc_test6(a: Arc>) {} | ^^^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL | pub fn arc_test6(a: Arc>) {} = help: consider using just `Arc` or `Rc` error: usage of `Arc>>` - --> $DIR/redundant_allocation.rs:71:27 + --> $DIR/redundant_allocation.rs:61:27 | LL | pub fn arc_test8() -> Arc>> { | ^^^^^^^^^^^^^^^^^^^^^ @@ -117,7 +117,7 @@ LL | pub fn arc_test8() -> Arc>> { = help: consider using just `Arc>` or `Box>` error: usage of `Arc>` - --> $DIR/redundant_allocation.rs:75:30 + --> $DIR/redundant_allocation.rs:65:30 | LL | pub fn arc_test9(foo: Arc>) -> Arc>> { | ^^^^^^^^^^ @@ -126,7 +126,7 @@ LL | pub fn arc_test9(foo: Arc>) -> Arc>> { = help: consider using just `Arc` or `Rc` error: usage of `Arc>>` - --> $DIR/redundant_allocation.rs:75:45 + --> $DIR/redundant_allocation.rs:65:45 | LL | pub fn arc_test9(foo: Arc>) -> Arc>> { | ^^^^^^^^^^^^^^^^ @@ -135,7 +135,7 @@ LL | pub fn arc_test9(foo: Arc>) -> Arc>> { = help: consider using just `Arc>` or `Rc>` error: usage of `Rc>>` - --> $DIR/redundant_allocation.rs:97:27 + --> $DIR/redundant_allocation.rs:87:27 | LL | pub fn test_rc_box(_: Rc>>) {} | ^^^^^^^^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL | pub fn test_rc_box(_: Rc>>) {} = help: consider using just `Rc>` or `Box>` error: usage of `Rc>>` - --> $DIR/redundant_allocation.rs:129:31 + --> $DIR/redundant_allocation.rs:119:31 | LL | pub fn test_rc_box_str(_: Rc>>) {} | ^^^^^^^^^^^^^^^^^ @@ -153,7 +153,7 @@ LL | pub fn test_rc_box_str(_: Rc>>) {} = help: consider using just `Rc>` or `Box>` error: usage of `Rc>>` - --> $DIR/redundant_allocation.rs:130:33 + --> $DIR/redundant_allocation.rs:120:33 | LL | pub fn test_rc_box_slice(_: Rc>>) {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -162,7 +162,7 @@ LL | pub fn test_rc_box_slice(_: Rc>>) {} = help: consider using just `Rc>` or `Box>` error: usage of `Rc>>` - --> $DIR/redundant_allocation.rs:131:32 + --> $DIR/redundant_allocation.rs:121:32 | LL | pub fn test_rc_box_path(_: Rc>>) {} | ^^^^^^^^^^^^^^^^^^ @@ -171,7 +171,7 @@ LL | pub fn test_rc_box_path(_: Rc>>) {} = help: consider using just `Rc>` or `Box>` error: usage of `Rc>>` - --> $DIR/redundant_allocation.rs:132:34 + --> $DIR/redundant_allocation.rs:122:34 | LL | pub fn test_rc_box_custom(_: Rc>>) {} | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/redundant_allocation_fixable.fixed b/tests/ui/redundant_allocation_fixable.fixed index e7ed84731..6db02718c 100644 --- a/tests/ui/redundant_allocation_fixable.fixed +++ b/tests/ui/redundant_allocation_fixable.fixed @@ -1,7 +1,7 @@ // run-rustfix #![warn(clippy::all)] #![allow(clippy::boxed_local, clippy::needless_pass_by_value)] -#![allow(clippy::blacklisted_name, unused_variables, dead_code)] +#![allow(clippy::disallowed_names, unused_variables, dead_code)] #![allow(unused_imports)] pub struct MyStruct; diff --git a/tests/ui/redundant_allocation_fixable.rs b/tests/ui/redundant_allocation_fixable.rs index de763f98b..c15806f30 100644 --- a/tests/ui/redundant_allocation_fixable.rs +++ b/tests/ui/redundant_allocation_fixable.rs @@ -1,7 +1,7 @@ // run-rustfix #![warn(clippy::all)] #![allow(clippy::boxed_local, clippy::needless_pass_by_value)] -#![allow(clippy::blacklisted_name, unused_variables, dead_code)] +#![allow(clippy::disallowed_names, unused_variables, dead_code)] #![allow(unused_imports)] pub struct MyStruct; diff --git a/tests/ui/redundant_closure_call_fixable.fixed b/tests/ui/redundant_closure_call_fixable.fixed index 0abca6fca..7cd687c95 100644 --- a/tests/ui/redundant_closure_call_fixable.fixed +++ b/tests/ui/redundant_closure_call_fixable.fixed @@ -1,8 +1,28 @@ // run-rustfix +#![feature(async_closure)] #![warn(clippy::redundant_closure_call)] #![allow(unused)] +async fn something() -> u32 { + 21 +} + +async fn something_else() -> u32 { + 2 +} + fn main() { let a = 42; + let b = async { + let x = something().await; + let y = something_else().await; + x * y + }; + let c = { + let x = 21; + let y = 2; + x * y + }; + let d = async { something().await }; } diff --git a/tests/ui/redundant_closure_call_fixable.rs b/tests/ui/redundant_closure_call_fixable.rs index f8b9d37a5..37e4d2238 100644 --- a/tests/ui/redundant_closure_call_fixable.rs +++ b/tests/ui/redundant_closure_call_fixable.rs @@ -1,8 +1,28 @@ // run-rustfix +#![feature(async_closure)] #![warn(clippy::redundant_closure_call)] #![allow(unused)] +async fn something() -> u32 { + 21 +} + +async fn something_else() -> u32 { + 2 +} + fn main() { let a = (|| 42)(); + let b = (async || { + let x = something().await; + let y = something_else().await; + x * y + })(); + let c = (|| { + let x = 21; + let y = 2; + x * y + })(); + let d = (async || something().await)(); } diff --git a/tests/ui/redundant_closure_call_fixable.stderr b/tests/ui/redundant_closure_call_fixable.stderr index afd704ef1..56a8e57c0 100644 --- a/tests/ui/redundant_closure_call_fixable.stderr +++ b/tests/ui/redundant_closure_call_fixable.stderr @@ -1,10 +1,56 @@ error: try not to call a closure in the expression where it is declared - --> $DIR/redundant_closure_call_fixable.rs:7:13 + --> $DIR/redundant_closure_call_fixable.rs:16:13 | LL | let a = (|| 42)(); | ^^^^^^^^^ help: try doing something like: `42` | = note: `-D clippy::redundant-closure-call` implied by `-D warnings` -error: aborting due to previous error +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:17:13 + | +LL | let b = (async || { + | _____________^ +LL | | let x = something().await; +LL | | let y = something_else().await; +LL | | x * y +LL | | })(); + | |________^ + | +help: try doing something like + | +LL ~ let b = async { +LL + let x = something().await; +LL + let y = something_else().await; +LL + x * y +LL ~ }; + | + +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:22:13 + | +LL | let c = (|| { + | _____________^ +LL | | let x = 21; +LL | | let y = 2; +LL | | x * y +LL | | })(); + | |________^ + | +help: try doing something like + | +LL ~ let c = { +LL + let x = 21; +LL + let y = 2; +LL + x * y +LL ~ }; + | + +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:27:13 + | +LL | let d = (async || something().await)(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async { something().await }` + +error: aborting due to 4 previous errors diff --git a/tests/ui/rename.fixed b/tests/ui/rename.fixed index 53288be94..9cbad2269 100644 --- a/tests/ui/rename.fixed +++ b/tests/ui/rename.fixed @@ -4,6 +4,7 @@ // run-rustfix +#![allow(clippy::disallowed_names)] #![allow(clippy::blocks_in_if_conditions)] #![allow(clippy::box_collection)] #![allow(clippy::redundant_static_lifetimes)] @@ -14,6 +15,7 @@ #![allow(clippy::for_loops_over_fallibles)] #![allow(clippy::useless_conversion)] #![allow(clippy::match_result_ok)] +#![allow(clippy::overly_complex_bool_expr)] #![allow(clippy::new_without_default)] #![allow(clippy::bind_instead_of_map)] #![allow(clippy::expect_used)] @@ -33,6 +35,7 @@ #![allow(temporary_cstring_as_ptr)] #![allow(unknown_lints)] #![allow(unused_labels)] +#![warn(clippy::disallowed_names)] #![warn(clippy::blocks_in_if_conditions)] #![warn(clippy::blocks_in_if_conditions)] #![warn(clippy::box_collection)] @@ -45,6 +48,7 @@ #![warn(clippy::for_loops_over_fallibles)] #![warn(clippy::useless_conversion)] #![warn(clippy::match_result_ok)] +#![warn(clippy::overly_complex_bool_expr)] #![warn(clippy::new_without_default)] #![warn(clippy::bind_instead_of_map)] #![warn(clippy::expect_used)] diff --git a/tests/ui/rename.rs b/tests/ui/rename.rs index 539f34f84..9153c0dab 100644 --- a/tests/ui/rename.rs +++ b/tests/ui/rename.rs @@ -4,6 +4,7 @@ // run-rustfix +#![allow(clippy::disallowed_names)] #![allow(clippy::blocks_in_if_conditions)] #![allow(clippy::box_collection)] #![allow(clippy::redundant_static_lifetimes)] @@ -14,6 +15,7 @@ #![allow(clippy::for_loops_over_fallibles)] #![allow(clippy::useless_conversion)] #![allow(clippy::match_result_ok)] +#![allow(clippy::overly_complex_bool_expr)] #![allow(clippy::new_without_default)] #![allow(clippy::bind_instead_of_map)] #![allow(clippy::expect_used)] @@ -33,6 +35,7 @@ #![allow(temporary_cstring_as_ptr)] #![allow(unknown_lints)] #![allow(unused_labels)] +#![warn(clippy::blacklisted_name)] #![warn(clippy::block_in_if_condition_expr)] #![warn(clippy::block_in_if_condition_stmt)] #![warn(clippy::box_vec)] @@ -45,6 +48,7 @@ #![warn(clippy::for_loop_over_result)] #![warn(clippy::identity_conversion)] #![warn(clippy::if_let_some_result)] +#![warn(clippy::logic_bug)] #![warn(clippy::new_without_default_derive)] #![warn(clippy::option_and_then_some)] #![warn(clippy::option_expect_used)] diff --git a/tests/ui/rename.stderr b/tests/ui/rename.stderr index 8ea46b580..9c03ea914 100644 --- a/tests/ui/rename.stderr +++ b/tests/ui/rename.stderr @@ -1,214 +1,226 @@ -error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions` - --> $DIR/rename.rs:36:9 +error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names` + --> $DIR/rename.rs:38:9 | -LL | #![warn(clippy::block_in_if_condition_expr)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` +LL | #![warn(clippy::blacklisted_name)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names` | = note: `-D renamed-and-removed-lints` implied by `-D warnings` +error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions` + --> $DIR/rename.rs:39:9 + | +LL | #![warn(clippy::block_in_if_condition_expr)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` + error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions` - --> $DIR/rename.rs:37:9 + --> $DIR/rename.rs:40:9 | LL | #![warn(clippy::block_in_if_condition_stmt)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` error: lint `clippy::box_vec` has been renamed to `clippy::box_collection` - --> $DIR/rename.rs:38:9 + --> $DIR/rename.rs:41:9 | LL | #![warn(clippy::box_vec)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection` error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes` - --> $DIR/rename.rs:39:9 + --> $DIR/rename.rs:42:9 | LL | #![warn(clippy::const_static_lifetime)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes` error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity` - --> $DIR/rename.rs:40:9 + --> $DIR/rename.rs:43:9 | LL | #![warn(clippy::cyclomatic_complexity)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity` error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods` - --> $DIR/rename.rs:41:9 + --> $DIR/rename.rs:44:9 | LL | #![warn(clippy::disallowed_method)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods` error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types` - --> $DIR/rename.rs:42:9 + --> $DIR/rename.rs:45:9 | LL | #![warn(clippy::disallowed_type)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types` error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression` - --> $DIR/rename.rs:43:9 + --> $DIR/rename.rs:46:9 | LL | #![warn(clippy::eval_order_dependence)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression` error: lint `clippy::for_loop_over_option` has been renamed to `clippy::for_loops_over_fallibles` - --> $DIR/rename.rs:44:9 + --> $DIR/rename.rs:47:9 | LL | #![warn(clippy::for_loop_over_option)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::for_loops_over_fallibles` error: lint `clippy::for_loop_over_result` has been renamed to `clippy::for_loops_over_fallibles` - --> $DIR/rename.rs:45:9 + --> $DIR/rename.rs:48:9 | LL | #![warn(clippy::for_loop_over_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::for_loops_over_fallibles` error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion` - --> $DIR/rename.rs:46:9 + --> $DIR/rename.rs:49:9 | LL | #![warn(clippy::identity_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion` error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok` - --> $DIR/rename.rs:47:9 + --> $DIR/rename.rs:50:9 | LL | #![warn(clippy::if_let_some_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok` +error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr` + --> $DIR/rename.rs:51:9 + | +LL | #![warn(clippy::logic_bug)] + | ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr` + error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default` - --> $DIR/rename.rs:48:9 + --> $DIR/rename.rs:52:9 | LL | #![warn(clippy::new_without_default_derive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default` error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map` - --> $DIR/rename.rs:49:9 + --> $DIR/rename.rs:53:9 | LL | #![warn(clippy::option_and_then_some)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map` error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used` - --> $DIR/rename.rs:50:9 + --> $DIR/rename.rs:54:9 | LL | #![warn(clippy::option_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:51:9 + --> $DIR/rename.rs:55:9 | LL | #![warn(clippy::option_map_unwrap_or)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:52:9 + --> $DIR/rename.rs:56:9 | LL | #![warn(clippy::option_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used` - --> $DIR/rename.rs:53:9 + --> $DIR/rename.rs:57:9 | LL | #![warn(clippy::option_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow` - --> $DIR/rename.rs:54:9 + --> $DIR/rename.rs:58:9 | LL | #![warn(clippy::ref_in_deref)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow` error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used` - --> $DIR/rename.rs:55:9 + --> $DIR/rename.rs:59:9 | LL | #![warn(clippy::result_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:56:9 + --> $DIR/rename.rs:60:9 | LL | #![warn(clippy::result_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used` - --> $DIR/rename.rs:57:9 + --> $DIR/rename.rs:61:9 | LL | #![warn(clippy::result_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str` - --> $DIR/rename.rs:58:9 + --> $DIR/rename.rs:62:9 | LL | #![warn(clippy::single_char_push_str)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str` error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions` - --> $DIR/rename.rs:59:9 + --> $DIR/rename.rs:63:9 | LL | #![warn(clippy::stutter)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions` error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl` - --> $DIR/rename.rs:60:9 + --> $DIR/rename.rs:64:9 | LL | #![warn(clippy::to_string_in_display)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl` error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters` - --> $DIR/rename.rs:61:9 + --> $DIR/rename.rs:65:9 | LL | #![warn(clippy::zero_width_space)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters` error: lint `clippy::drop_bounds` has been renamed to `drop_bounds` - --> $DIR/rename.rs:62:9 + --> $DIR/rename.rs:66:9 | LL | #![warn(clippy::drop_bounds)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds` error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` - --> $DIR/rename.rs:63:9 + --> $DIR/rename.rs:67:9 | LL | #![warn(clippy::into_iter_on_array)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter` error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering` - --> $DIR/rename.rs:64:9 + --> $DIR/rename.rs:68:9 | LL | #![warn(clippy::invalid_atomic_ordering)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering` error: lint `clippy::invalid_ref` has been renamed to `invalid_value` - --> $DIR/rename.rs:65:9 + --> $DIR/rename.rs:69:9 | LL | #![warn(clippy::invalid_ref)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value` error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums` - --> $DIR/rename.rs:66:9 + --> $DIR/rename.rs:70:9 | LL | #![warn(clippy::mem_discriminant_non_enum)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums` error: lint `clippy::panic_params` has been renamed to `non_fmt_panics` - --> $DIR/rename.rs:67:9 + --> $DIR/rename.rs:71:9 | LL | #![warn(clippy::panic_params)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics` error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr` - --> $DIR/rename.rs:68:9 + --> $DIR/rename.rs:72:9 | LL | #![warn(clippy::temporary_cstring_as_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr` error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` - --> $DIR/rename.rs:69:9 + --> $DIR/rename.rs:73:9 | LL | #![warn(clippy::unknown_clippy_lints)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints` error: lint `clippy::unused_label` has been renamed to `unused_labels` - --> $DIR/rename.rs:70:9 + --> $DIR/rename.rs:74:9 | LL | #![warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` -error: aborting due to 35 previous errors +error: aborting due to 37 previous errors diff --git a/tests/ui/same_functions_in_if_condition.rs b/tests/ui/same_functions_in_if_condition.rs index 3d2295912..a48829caa 100644 --- a/tests/ui/same_functions_in_if_condition.rs +++ b/tests/ui/same_functions_in_if_condition.rs @@ -48,9 +48,9 @@ fn ifs_same_cond_fn() { } let mut v = vec![1]; - if v.pop() == None { + if v.pop().is_none() { //~ ERROR ifs same condition - } else if v.pop() == None { + } else if v.pop().is_none() { } if v.len() == 42 { diff --git a/tests/ui/same_functions_in_if_condition.stderr b/tests/ui/same_functions_in_if_condition.stderr index 71e82910e..cd438b830 100644 --- a/tests/ui/same_functions_in_if_condition.stderr +++ b/tests/ui/same_functions_in_if_condition.stderr @@ -50,14 +50,14 @@ LL | if obj.method_arg(a) { error: this `if` has the same function call as a previous `if` --> $DIR/same_functions_in_if_condition.rs:53:15 | -LL | } else if v.pop() == None { - | ^^^^^^^^^^^^^^^ +LL | } else if v.pop().is_none() { + | ^^^^^^^^^^^^^^^^^ | note: same as this --> $DIR/same_functions_in_if_condition.rs:51:8 | -LL | if v.pop() == None { - | ^^^^^^^^^^^^^^^ +LL | if v.pop().is_none() { + | ^^^^^^^^^^^^^^^^^ error: this `if` has the same function call as a previous `if` --> $DIR/same_functions_in_if_condition.rs:58:15 diff --git a/tests/ui/skip_while_next.rs b/tests/ui/skip_while_next.rs index a522c0f08..a551c19d9 100644 --- a/tests/ui/skip_while_next.rs +++ b/tests/ui/skip_while_next.rs @@ -1,7 +1,7 @@ // aux-build:option_helpers.rs #![warn(clippy::skip_while_next)] -#![allow(clippy::blacklisted_name)] +#![allow(clippy::disallowed_names)] extern crate option_helpers; use option_helpers::IteratorFalsePositives; diff --git a/tests/ui/swap.fixed b/tests/ui/swap.fixed index 3329efbd4..24b229235 100644 --- a/tests/ui/swap.fixed +++ b/tests/ui/swap.fixed @@ -2,7 +2,7 @@ #![warn(clippy::all)] #![allow( - clippy::blacklisted_name, + clippy::disallowed_names, clippy::no_effect, clippy::redundant_clone, redundant_semicolons, diff --git a/tests/ui/swap.rs b/tests/ui/swap.rs index 8179ac1f2..a318c2791 100644 --- a/tests/ui/swap.rs +++ b/tests/ui/swap.rs @@ -2,7 +2,7 @@ #![warn(clippy::all)] #![allow( - clippy::blacklisted_name, + clippy::disallowed_names, clippy::no_effect, clippy::redundant_clone, redundant_semicolons, diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs index 8f78f16a0..c0c64ebca 100644 --- a/tests/ui/trivially_copy_pass_by_ref.rs +++ b/tests/ui/trivially_copy_pass_by_ref.rs @@ -2,7 +2,7 @@ // normalize-stderr-test "\(limit: \d+ byte\)" -> "(limit: N byte)" #![deny(clippy::trivially_copy_pass_by_ref)] -#![allow(clippy::blacklisted_name, clippy::redundant_field_names)] +#![allow(clippy::disallowed_names, clippy::redundant_field_names)] #[derive(Copy, Clone)] struct Foo(u32); diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs index 38be87bdd..7bf3adc07 100644 --- a/tests/ui/unit_arg.rs +++ b/tests/ui/unit_arg.rs @@ -1,3 +1,5 @@ +// aux-build: proc_macro_with_span.rs + #![warn(clippy::unit_arg)] #![allow( clippy::no_effect, @@ -8,9 +10,13 @@ clippy::or_fun_call, clippy::needless_question_mark, clippy::self_named_constructors, - clippy::let_unit_value + clippy::let_unit_value, + clippy::never_loop )] +extern crate proc_macro_with_span; + +use proc_macro_with_span::with_span; use std::fmt::Debug; fn foo(t: T) { @@ -127,6 +133,10 @@ fn returning_expr() -> Option<()> { fn taking_multiple_units(a: (), b: ()) {} +fn proc_macro() { + with_span!(span taking_multiple_units(unsafe { (); }, 'x: loop { break 'x (); })); +} + fn main() { bad(); ok(); diff --git a/tests/ui/unit_arg.stderr b/tests/ui/unit_arg.stderr index 11cfe66a3..1de9d44bb 100644 --- a/tests/ui/unit_arg.stderr +++ b/tests/ui/unit_arg.stderr @@ -1,5 +1,5 @@ error: passing a unit value to a function - --> $DIR/unit_arg.rs:57:5 + --> $DIR/unit_arg.rs:63:5 | LL | / foo({ LL | | 1; @@ -20,7 +20,7 @@ LL ~ foo(()); | error: passing a unit value to a function - --> $DIR/unit_arg.rs:60:5 + --> $DIR/unit_arg.rs:66:5 | LL | foo(foo(1)); | ^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL ~ foo(()); | error: passing a unit value to a function - --> $DIR/unit_arg.rs:61:5 + --> $DIR/unit_arg.rs:67:5 | LL | / foo({ LL | | foo(1); @@ -54,7 +54,7 @@ LL ~ foo(()); | error: passing a unit value to a function - --> $DIR/unit_arg.rs:66:5 + --> $DIR/unit_arg.rs:72:5 | LL | / b.bar({ LL | | 1; @@ -74,7 +74,7 @@ LL ~ b.bar(()); | error: passing unit values to a function - --> $DIR/unit_arg.rs:69:5 + --> $DIR/unit_arg.rs:75:5 | LL | taking_multiple_units(foo(0), foo(1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -87,7 +87,7 @@ LL ~ taking_multiple_units((), ()); | error: passing unit values to a function - --> $DIR/unit_arg.rs:70:5 + --> $DIR/unit_arg.rs:76:5 | LL | / taking_multiple_units(foo(0), { LL | | foo(1); @@ -110,7 +110,7 @@ LL ~ taking_multiple_units((), ()); | error: passing unit values to a function - --> $DIR/unit_arg.rs:74:5 + --> $DIR/unit_arg.rs:80:5 | LL | / taking_multiple_units( LL | | { @@ -146,7 +146,7 @@ LL ~ ); | error: passing a unit value to a function - --> $DIR/unit_arg.rs:85:13 + --> $DIR/unit_arg.rs:91:13 | LL | None.or(Some(foo(2))); | ^^^^^^^^^^^^ @@ -160,7 +160,7 @@ LL ~ }); | error: passing a unit value to a function - --> $DIR/unit_arg.rs:88:5 + --> $DIR/unit_arg.rs:94:5 | LL | foo(foo(())); | ^^^^^^^^^^^^ @@ -172,7 +172,7 @@ LL ~ foo(()); | error: passing a unit value to a function - --> $DIR/unit_arg.rs:125:5 + --> $DIR/unit_arg.rs:131:5 | LL | Some(foo(1)) | ^^^^^^^^^^^^ diff --git a/tests/ui/unwrap_expect_used.rs b/tests/ui/unwrap_expect_used.rs new file mode 100644 index 000000000..0d4a0504a --- /dev/null +++ b/tests/ui/unwrap_expect_used.rs @@ -0,0 +1,10 @@ +#![warn(clippy::unwrap_used, clippy::expect_used)] + +fn main() { + Some(3).unwrap(); + Some(3).expect("Hello world!"); + + let a: Result = Ok(3); + a.unwrap(); + a.expect("Hello world!"); +} diff --git a/tests/ui/unwrap_expect_used.stderr b/tests/ui/unwrap_expect_used.stderr new file mode 100644 index 000000000..f54bfd617 --- /dev/null +++ b/tests/ui/unwrap_expect_used.stderr @@ -0,0 +1,36 @@ +error: used `unwrap()` on `an Option` value + --> $DIR/unwrap_expect_used.rs:4:5 + | +LL | Some(3).unwrap(); + | ^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::unwrap-used` implied by `-D warnings` + = help: if this value is `None`, it will panic + +error: used `expect()` on `an Option` value + --> $DIR/unwrap_expect_used.rs:5:5 + | +LL | Some(3).expect("Hello world!"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::expect-used` implied by `-D warnings` + = help: if this value is `None`, it will panic + +error: used `unwrap()` on `a Result` value + --> $DIR/unwrap_expect_used.rs:8:5 + | +LL | a.unwrap(); + | ^^^^^^^^^^ + | + = help: if this value is an `Err`, it will panic + +error: used `expect()` on `a Result` value + --> $DIR/unwrap_expect_used.rs:9:5 + | +LL | a.expect("Hello world!"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: if this value is an `Err`, it will panic + +error: aborting due to 4 previous errors + diff --git a/tests/ui/used_underscore_binding.rs b/tests/ui/used_underscore_binding.rs index d20977d55..322083511 100644 --- a/tests/ui/used_underscore_binding.rs +++ b/tests/ui/used_underscore_binding.rs @@ -2,7 +2,7 @@ #![feature(rustc_private)] #![warn(clippy::all)] -#![allow(clippy::blacklisted_name, clippy::eq_op)] +#![allow(clippy::disallowed_names, clippy::eq_op)] #![warn(clippy::used_underscore_binding)] #[macro_use]