mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-23 13:13:34 +00:00
Merge remote-tracking branch 'upstream/master' into rustup
This commit is contained in:
commit
aa3247c891
106 changed files with 2719 additions and 549 deletions
23
.github/ISSUE_TEMPLATE/new_lint.yml
vendored
23
.github/ISSUE_TEMPLATE/new_lint.yml
vendored
|
@ -12,29 +12,6 @@ body:
|
|||
description: What does this lint do?
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: lint-name
|
||||
attributes:
|
||||
label: Lint Name
|
||||
description: Please provide the lint name.
|
||||
- type: dropdown
|
||||
id: category
|
||||
attributes:
|
||||
label: Category
|
||||
description: >
|
||||
What category should this lint go into? If you're unsure you can select
|
||||
multiple categories. You can find a category description in the
|
||||
`README`.
|
||||
multiple: true
|
||||
options:
|
||||
- correctness
|
||||
- suspicious
|
||||
- style
|
||||
- complexity
|
||||
- perf
|
||||
- pedantic
|
||||
- restriction
|
||||
- cargo
|
||||
- type: textarea
|
||||
id: advantage
|
||||
attributes:
|
||||
|
|
130
CHANGELOG.md
130
CHANGELOG.md
|
@ -6,7 +6,132 @@ document.
|
|||
|
||||
## Unreleased / Beta / In Rust Nightly
|
||||
|
||||
[149392b0...master](https://github.com/rust-lang/rust-clippy/compare/149392b0...master)
|
||||
[83e42a23...master](https://github.com/rust-lang/rust-clippy/compare/83e42a23...master)
|
||||
|
||||
## Rust 1.70
|
||||
|
||||
Current beta, released 2023-06-01
|
||||
|
||||
[149392b0...83e42a23](https://github.com/rust-lang/rust-clippy/compare/149392b0...83e42a23)
|
||||
|
||||
### New Lints
|
||||
|
||||
* [`large_futures`]
|
||||
[#10414](https://github.com/rust-lang/rust-clippy/pull/10414)
|
||||
* [`missing_assert_message`]
|
||||
[#10362](https://github.com/rust-lang/rust-clippy/pull/10362)
|
||||
* [`clear_with_drain`]
|
||||
[#10528](https://github.com/rust-lang/rust-clippy/pull/10528)
|
||||
* [`redundant_async_block`]
|
||||
[#10448](https://github.com/rust-lang/rust-clippy/pull/10448)
|
||||
* [`collection_is_never_read`]
|
||||
[#10415](https://github.com/rust-lang/rust-clippy/pull/10415)
|
||||
* [`let_with_type_underscore`]
|
||||
[#10467](https://github.com/rust-lang/rust-clippy/pull/10467)
|
||||
* [`tests_outside_test_module`]
|
||||
[#10543](https://github.com/rust-lang/rust-clippy/pull/10543)
|
||||
* [`allow_attributes`]
|
||||
[#10481](https://github.com/rust-lang/rust-clippy/pull/10481)
|
||||
* [`suspicious_doc_comments`]
|
||||
[#10497](https://github.com/rust-lang/rust-clippy/pull/10497)
|
||||
* [`unnecessary_box_returns`]
|
||||
[#9102](https://github.com/rust-lang/rust-clippy/pull/9102)
|
||||
* [`manual_main_separator_str`]
|
||||
[#10483](https://github.com/rust-lang/rust-clippy/pull/10483)
|
||||
* [`unnecessary_struct_initialization`]
|
||||
[#10489](https://github.com/rust-lang/rust-clippy/pull/10489)
|
||||
* [`manual_slice_size_calculation`]
|
||||
[#10601](https://github.com/rust-lang/rust-clippy/pull/10601)
|
||||
* [`lines_filter_map_ok`]
|
||||
[#10534](https://github.com/rust-lang/rust-clippy/pull/10534)
|
||||
|
||||
### Moves and Deprecations
|
||||
|
||||
* Moved [`let_underscore_untyped`] to `restriction`
|
||||
[#10442](https://github.com/rust-lang/rust-clippy/pull/10442)
|
||||
|
||||
### Enhancements
|
||||
|
||||
* [`extra_unused_type_parameters`]: No longer lints on public items if `avoid-breaking-exported-api` is set
|
||||
[#10536](https://github.com/rust-lang/rust-clippy/pull/10536)
|
||||
* [`len_without_is_empty`]: Now also detects `async` functions
|
||||
[#10359](https://github.com/rust-lang/rust-clippy/pull/10359)
|
||||
* [`arithmetic_side_effects`]: Now correctly handles divisions and modulo expressions if the right-hand-side
|
||||
is unknown
|
||||
[#10585](https://github.com/rust-lang/rust-clippy/pull/10585)
|
||||
* [`nonminimal_bool`]: No longer ignores `#[allow]` attributes
|
||||
[#10588](https://github.com/rust-lang/rust-clippy/pull/10588)
|
||||
* [`uninit_vec`], [`uninit_assumed_init`]: Now uses a better heuristic
|
||||
[#10520](https://github.com/rust-lang/rust-clippy/pull/10520)
|
||||
* [`ifs_same_cond`]: Now also detects immutable method calls.
|
||||
[#10350](https://github.com/rust-lang/rust-clippy/pull/10350)
|
||||
* [`arithmetic_side_effects`]: No longer lints on right or left shifts with constant integers, as the
|
||||
compiler warns about them
|
||||
[#10309](https://github.com/rust-lang/rust-clippy/pull/10309)
|
||||
* [`items_after_statements`]: `#[allow(items_after_statements)]` now works on items
|
||||
[#10542](https://github.com/rust-lang/rust-clippy/pull/10542)
|
||||
* [`significant_drop_tightening`]: Was optimized
|
||||
[#10533](https://github.com/rust-lang/rust-clippy/pull/10533)
|
||||
|
||||
### False Positive Fixes
|
||||
|
||||
* [`single_component_path_imports`]: No longer lints if the import is used relative to `self`
|
||||
[#10566](https://github.com/rust-lang/rust-clippy/pull/10566)
|
||||
* [`derivable_impls`]: No longer suggests deriving `Default` on generics with implicit arguments
|
||||
[#10399](https://github.com/rust-lang/rust-clippy/pull/10399)
|
||||
* [`let_unit_value`]: No longer lints if the expression contains an `await`
|
||||
[#10439](https://github.com/rust-lang/rust-clippy/pull/10439)
|
||||
* [`double_must_use`]: Now ignores `async` functions
|
||||
[#10589](https://github.com/rust-lang/rust-clippy/pull/10589)
|
||||
* [`manual_clamp`]: No longer lints in constant context
|
||||
[#10479](https://github.com/rust-lang/rust-clippy/pull/10479)
|
||||
* [`almost_swapped`]: Now ignores external macros
|
||||
[#10502](https://github.com/rust-lang/rust-clippy/pull/10502)
|
||||
* [`nonminimal_bool`]: Now ignores macros
|
||||
[#10527](https://github.com/rust-lang/rust-clippy/pull/10527)
|
||||
* [`needless_return`]: No longer lints match statements with incompatible branches
|
||||
[#10593](https://github.com/rust-lang/rust-clippy/pull/10593)
|
||||
* [`use_self`]: Do not suggest using `Self` in const generic parameters
|
||||
[#10375](https://github.com/rust-lang/rust-clippy/pull/10375)
|
||||
* [`mem_replace_option_with_none`]: No longer lints on field expressions
|
||||
[#10594](https://github.com/rust-lang/rust-clippy/pull/10594)
|
||||
* [`items_after_statements`]: No longer lints on times from macros
|
||||
[#10542](https://github.com/rust-lang/rust-clippy/pull/10542)
|
||||
* [`print_literal`], [`write_literal`]: No longer lint strings coming from the `file!()` macro
|
||||
[#10573](https://github.com/rust-lang/rust-clippy/pull/10573)
|
||||
* [`uninit_vec`], [`uninit_assumed_init`]: Now check the types inside arrays and tuples
|
||||
[#10553](https://github.com/rust-lang/rust-clippy/pull/10553)
|
||||
* [`almost_swapped`]: No longer lints if a variable is assigned to itself
|
||||
[#10499](https://github.com/rust-lang/rust-clippy/pull/10499)
|
||||
* [`missing_docs_in_private_items`]: No longer lints on public items
|
||||
[#10324](https://github.com/rust-lang/rust-clippy/pull/10324)
|
||||
|
||||
### Suggestion Fixes/Improvements
|
||||
|
||||
* [`extra_unused_type_parameters`]: The suggestion is now machine applicable
|
||||
[#10536](https://github.com/rust-lang/rust-clippy/pull/10536)
|
||||
* [`match_single_binding`]: Now adds a semicolon after the suggestion
|
||||
[#10470](https://github.com/rust-lang/rust-clippy/pull/10470)
|
||||
* [`missing_const_for_fn`]: Now includes a note if the change could break compatibility
|
||||
[#10618](https://github.com/rust-lang/rust-clippy/pull/10618)
|
||||
* [`cast_possible_truncation`]: Corrected suggestion for float and wildcard casts
|
||||
[#10496](https://github.com/rust-lang/rust-clippy/pull/10496)
|
||||
* [`transmutes_expressible_as_ptr_casts`]: The suggestion now includes parentheses when they are required
|
||||
[#10454](https://github.com/rust-lang/rust-clippy/pull/10454)
|
||||
|
||||
### ICE Fixes
|
||||
|
||||
* [`needless_borrow`]: No longer panics on ambiguous projections
|
||||
[#10403](https://github.com/rust-lang/rust-clippy/pull/10403)
|
||||
* [`multiple_unsafe_ops_per_block`]: Fix ICE when calling a function-like object in an unsafe block
|
||||
[#10405](https://github.com/rust-lang/rust-clippy/pull/10405)
|
||||
|
||||
### Others
|
||||
|
||||
* `clippy-driver` now searches parent directories for `clippy.toml` files
|
||||
[#10592](https://github.com/rust-lang/rust-clippy/pull/10592)
|
||||
* Fixed a deserialization error for the `array-size-threshold` config value
|
||||
[#10423](https://github.com/rust-lang/rust-clippy/pull/10423)
|
||||
|
||||
## Rust 1.69
|
||||
|
||||
|
@ -4838,6 +4963,7 @@ Released 2018-09-13
|
|||
[`missing_docs_in_private_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items
|
||||
[`missing_enforced_import_renames`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames
|
||||
[`missing_errors_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc
|
||||
[`missing_fields_in_debug`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_fields_in_debug
|
||||
[`missing_inline_in_public_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_inline_in_public_items
|
||||
[`missing_panics_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc
|
||||
[`missing_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc
|
||||
|
@ -4874,6 +5000,7 @@ Released 2018-09-13
|
|||
[`needless_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_collect
|
||||
[`needless_continue`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_continue
|
||||
[`needless_doctest_main`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_doctest_main
|
||||
[`needless_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_else
|
||||
[`needless_for_each`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_for_each
|
||||
[`needless_late_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_late_init
|
||||
[`needless_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
|
||||
|
@ -4949,6 +5076,7 @@ Released 2018-09-13
|
|||
[`println_empty_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#println_empty_string
|
||||
[`ptr_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg
|
||||
[`ptr_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr
|
||||
[`ptr_cast_constness`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_cast_constness
|
||||
[`ptr_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_eq
|
||||
[`ptr_offset_with_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_offset_with_cast
|
||||
[`pub_enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_enum_variant_names
|
||||
|
|
|
@ -35,11 +35,6 @@ walkdir = "2.3"
|
|||
# This is used by the `collect-metadata` alias.
|
||||
filetime = "0.2"
|
||||
|
||||
# A noop dependency that changes in the Rust repository, it's a bit of a hack.
|
||||
# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust`
|
||||
# for more information.
|
||||
rustc-workspace-hack = "1.0"
|
||||
|
||||
# UI test dependencies
|
||||
clap = { version = "4.1.4", features = ["derive"] }
|
||||
clippy_utils = { path = "clippy_utils" }
|
||||
|
|
|
@ -2,8 +2,14 @@
|
|||
|
||||
> **Note:** The configuration file is unstable and may be deprecated in the future.
|
||||
|
||||
Some lints can be configured in a TOML file named `clippy.toml` or `.clippy.toml`. It contains a
|
||||
basic `variable = value` mapping e.g.
|
||||
Some lints can be configured in a TOML file named `clippy.toml` or `.clippy.toml`, which is searched for in:
|
||||
|
||||
1. The directory specified by the `CLIPPY_CONF_DIR` environment variable, or
|
||||
2. The directory specified by the
|
||||
[CARGO_MANIFEST_DIR](https://doc.rust-lang.org/cargo/reference/environment-variables.html) environment variable, or
|
||||
3. The current directory.
|
||||
|
||||
It contains a basic `variable = value` mapping e.g.
|
||||
|
||||
```toml
|
||||
avoid-breaking-exported-api = false
|
||||
|
|
|
@ -630,8 +630,14 @@ Before submitting your PR make sure you followed all the basic requirements:
|
|||
|
||||
## Adding configuration to a lint
|
||||
|
||||
Clippy supports the configuration of lints values using a `clippy.toml` file in
|
||||
the workspace directory. Adding a configuration to a lint can be useful for
|
||||
Clippy supports the configuration of lints values using a `clippy.toml` file which is searched for in:
|
||||
|
||||
1. The directory specified by the `CLIPPY_CONF_DIR` environment variable, or
|
||||
2. The directory specified by the
|
||||
[CARGO_MANIFEST_DIR](https://doc.rust-lang.org/cargo/reference/environment-variables.html) environment variable, or
|
||||
3. The current directory.
|
||||
|
||||
Adding a configuration to a lint can be useful for
|
||||
thresholds or to constrain some behavior that can be seen as a false positive
|
||||
for some users. Adding a configuration is done in the following steps:
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
use clap::{Arg, ArgAction, ArgMatches, Command};
|
||||
use clippy_dev::{bless, dogfood, fmt, lint, new_lint, serve, setup, update_lints};
|
||||
use indoc::indoc;
|
||||
use std::convert::Infallible;
|
||||
|
||||
fn main() {
|
||||
let matches = get_clap_config();
|
||||
|
@ -180,7 +181,8 @@ fn get_clap_config() -> ArgMatches {
|
|||
.short('n')
|
||||
.long("name")
|
||||
.help("Name of the new lint in snake case, ex: fn_too_long")
|
||||
.required(true),
|
||||
.required(true)
|
||||
.value_parser(|name: &str| Ok::<_, Infallible>(name.replace('-', "_"))),
|
||||
Arg::new("category")
|
||||
.short('c')
|
||||
.long("category")
|
||||
|
|
|
@ -20,15 +20,13 @@ quine-mc_cluskey = "0.2"
|
|||
regex-syntax = "0.7"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = { version = "1.0", optional = true }
|
||||
tempfile = { version = "3.2", optional = true }
|
||||
tempfile = { version = "3.3.0", optional = true }
|
||||
toml = "0.5"
|
||||
unicode-normalization = "0.1"
|
||||
unicode-script = { version = "0.5", default-features = false }
|
||||
semver = "1.0"
|
||||
rustc-semver = "1.1"
|
||||
# NOTE: cargo requires serde feat in its url dep
|
||||
# see <https://github.com/rust-lang/rust/pull/63587#issuecomment-522343864>
|
||||
url = { version = "2.2", features = ["serde"] }
|
||||
url = "2.2"
|
||||
|
||||
[features]
|
||||
deny-warnings = ["clippy_utils/deny-warnings"]
|
||||
|
|
|
@ -40,7 +40,7 @@ declare_clippy_lint! {
|
|||
/// a.len()
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.69.0"]
|
||||
#[clippy::version = "1.70.0"]
|
||||
pub ALLOW_ATTRIBUTES,
|
||||
restriction,
|
||||
"`#[allow]` will not trigger if a warning isn't found. `#[expect]` triggers if there are no warnings."
|
||||
|
|
|
@ -85,8 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInIfConditions {
|
|||
);
|
||||
}
|
||||
} else {
|
||||
let span =
|
||||
block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span);
|
||||
let span = block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span);
|
||||
if span.from_expansion() || expr.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -88,7 +88,6 @@ impl<'tcx> LateLintPass<'tcx> for NonminimalBool {
|
|||
NonminimalBoolVisitor { cx }.visit_body(body);
|
||||
}
|
||||
}
|
||||
|
||||
struct NonminimalBoolVisitor<'a, 'tcx> {
|
||||
cx: &'a LateContext<'tcx>,
|
||||
}
|
||||
|
@ -473,6 +472,10 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
|
|||
self.bool_expr(e);
|
||||
},
|
||||
ExprKind::Unary(UnOp::Not, inner) => {
|
||||
if let ExprKind::Unary(UnOp::Not, ex) = inner.kind &&
|
||||
!self.cx.typeck_results().node_types()[ex.hir_id].is_bool() {
|
||||
return;
|
||||
}
|
||||
if self.cx.typeck_results().node_types()[inner.hir_id].is_bool() {
|
||||
self.bool_expr(e);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ mod fn_to_numeric_cast;
|
|||
mod fn_to_numeric_cast_any;
|
||||
mod fn_to_numeric_cast_with_truncation;
|
||||
mod ptr_as_ptr;
|
||||
mod ptr_cast_constness;
|
||||
mod unnecessary_cast;
|
||||
mod utils;
|
||||
|
||||
|
@ -363,7 +364,7 @@ declare_clippy_lint! {
|
|||
/// namely `*const T` to `*const U` and `*mut T` to `*mut U`.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Though `as` casts between raw pointers is not terrible, `pointer::cast` is safer because
|
||||
/// Though `as` casts between raw pointers are not terrible, `pointer::cast` is safer because
|
||||
/// it cannot accidentally change the pointer's mutability nor cast the pointer to other types like `usize`.
|
||||
///
|
||||
/// ### Example
|
||||
|
@ -386,6 +387,34 @@ declare_clippy_lint! {
|
|||
"casting using `as` from and to raw pointers that doesn't change its mutability, where `pointer::cast` could take the place of `as`"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for `as` casts between raw pointers which change its constness, namely `*const T` to
|
||||
/// `*mut T` and `*mut T` to `*const T`.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Though `as` casts between raw pointers are not terrible, `pointer::cast_mut` and
|
||||
/// `pointer::cast_const` are safer because they cannot accidentally cast the pointer to another
|
||||
/// type.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
/// let ptr: *const u32 = &42_u32;
|
||||
/// let mut_ptr = ptr as *mut u32;
|
||||
/// let ptr = mut_ptr as *const u32;
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// let ptr: *const u32 = &42_u32;
|
||||
/// let mut_ptr = ptr.cast_mut();
|
||||
/// let ptr = mut_ptr.cast_const();
|
||||
/// ```
|
||||
#[clippy::version = "1.71.0"]
|
||||
pub PTR_CAST_CONSTNESS,
|
||||
pedantic,
|
||||
"casting using `as` from and to raw pointers to change constness when specialized methods apply"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for casts from an enum type to an integral type which will definitely truncate the
|
||||
|
@ -652,6 +681,7 @@ impl_lint_pass!(Casts => [
|
|||
FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
|
||||
CHAR_LIT_AS_U8,
|
||||
PTR_AS_PTR,
|
||||
PTR_CAST_CONSTNESS,
|
||||
CAST_ENUM_TRUNCATION,
|
||||
CAST_ENUM_CONSTRUCTOR,
|
||||
CAST_ABS_TO_UNSIGNED,
|
||||
|
@ -685,6 +715,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
|
|||
return;
|
||||
}
|
||||
cast_slice_from_raw_parts::check(cx, expr, cast_expr, cast_to, &self.msrv);
|
||||
ptr_cast_constness::check(cx, expr, cast_expr, cast_from, cast_to, &self.msrv);
|
||||
as_ptr_cast_mut::check(cx, expr, cast_expr, cast_to);
|
||||
fn_to_numeric_cast_any::check(cx, expr, cast_expr, cast_from, cast_to);
|
||||
fn_to_numeric_cast::check(cx, expr, cast_expr, cast_from, cast_to);
|
||||
|
|
44
clippy_lints/src/casts/ptr_cast_constness.rs
Normal file
44
clippy_lints/src/casts/ptr_cast_constness.rs
Normal file
|
@ -0,0 +1,44 @@
|
|||
use clippy_utils::msrvs::POINTER_CAST_CONSTNESS;
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::{diagnostics::span_lint_and_sugg, msrvs::Msrv};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, Mutability};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::{self, Ty, TypeAndMut};
|
||||
|
||||
use super::PTR_CAST_CONSTNESS;
|
||||
|
||||
pub(super) fn check(
|
||||
cx: &LateContext<'_>,
|
||||
expr: &Expr<'_>,
|
||||
cast_expr: &Expr<'_>,
|
||||
cast_from: Ty<'_>,
|
||||
cast_to: Ty<'_>,
|
||||
msrv: &Msrv,
|
||||
) {
|
||||
if_chain! {
|
||||
if msrv.meets(POINTER_CAST_CONSTNESS);
|
||||
if let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, .. }) = cast_from.kind();
|
||||
if let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, .. }) = cast_to.kind();
|
||||
if matches!((from_mutbl, to_mutbl),
|
||||
(Mutability::Not, Mutability::Mut) | (Mutability::Mut, Mutability::Not));
|
||||
then {
|
||||
let sugg = Sugg::hir(cx, cast_expr, "_");
|
||||
let constness = match *to_mutbl {
|
||||
Mutability::Not => "const",
|
||||
Mutability::Mut => "mut",
|
||||
};
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
PTR_CAST_CONSTNESS,
|
||||
expr.span,
|
||||
"`as` casting between raw pointers while changing its constness",
|
||||
&format!("try `pointer::cast_{constness}`, a safer alternative"),
|
||||
format!("{}.cast_{constness}()", sugg.maybe_par()),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,7 +37,7 @@ declare_clippy_lint! {
|
|||
/// println!("{sample}");
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.69.0"]
|
||||
#[clippy::version = "1.70.0"]
|
||||
pub COLLECTION_IS_NEVER_READ,
|
||||
nursery,
|
||||
"a collection is never queried"
|
||||
|
|
|
@ -89,6 +89,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
|||
crate::casts::FN_TO_NUMERIC_CAST_ANY_INFO,
|
||||
crate::casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION_INFO,
|
||||
crate::casts::PTR_AS_PTR_INFO,
|
||||
crate::casts::PTR_CAST_CONSTNESS_INFO,
|
||||
crate::casts::UNNECESSARY_CAST_INFO,
|
||||
crate::checked_conversions::CHECKED_CONVERSIONS_INFO,
|
||||
crate::cognitive_complexity::COGNITIVE_COMPLEXITY_INFO,
|
||||
|
@ -427,6 +428,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
|||
crate::missing_const_for_fn::MISSING_CONST_FOR_FN_INFO,
|
||||
crate::missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS_INFO,
|
||||
crate::missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES_INFO,
|
||||
crate::missing_fields_in_debug::MISSING_FIELDS_IN_DEBUG_INFO,
|
||||
crate::missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS_INFO,
|
||||
crate::missing_trait_methods::MISSING_TRAIT_METHODS_INFO,
|
||||
crate::mixed_read_write_in_expression::DIVERGING_SUB_EXPRESSION_INFO,
|
||||
|
@ -447,6 +449,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
|||
crate::needless_bool::NEEDLESS_BOOL_ASSIGN_INFO,
|
||||
crate::needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE_INFO,
|
||||
crate::needless_continue::NEEDLESS_CONTINUE_INFO,
|
||||
crate::needless_else::NEEDLESS_ELSE_INFO,
|
||||
crate::needless_for_each::NEEDLESS_FOR_EACH_INFO,
|
||||
crate::needless_late_init::NEEDLESS_LATE_INIT_INFO,
|
||||
crate::needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS_INFO,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::{diagnostics::span_lint_and_sugg, match_def_path, paths};
|
||||
use clippy_utils::{diagnostics::span_lint_and_sugg, is_ty_alias, match_def_path, paths};
|
||||
use hir::{def::Res, ExprKind};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
|
@ -43,12 +43,23 @@ declare_clippy_lint! {
|
|||
}
|
||||
declare_lint_pass!(DefaultConstructedUnitStructs => [DEFAULT_CONSTRUCTED_UNIT_STRUCTS]);
|
||||
|
||||
fn is_alias(ty: hir::Ty<'_>) -> bool {
|
||||
if let hir::TyKind::Path(ref qpath) = ty.kind {
|
||||
is_ty_alias(qpath)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl LateLintPass<'_> for DefaultConstructedUnitStructs {
|
||||
fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
|
||||
if_chain!(
|
||||
// make sure we have a call to `Default::default`
|
||||
if let hir::ExprKind::Call(fn_expr, &[]) = expr.kind;
|
||||
if let ExprKind::Path(ref qpath@ hir::QPath::TypeRelative(_,_)) = fn_expr.kind;
|
||||
if let ExprKind::Path(ref qpath @ hir::QPath::TypeRelative(base, _)) = fn_expr.kind;
|
||||
// make sure this isn't a type alias:
|
||||
// `<Foo as Bar>::Assoc` cannot be used as a constructor
|
||||
if !is_alias(*base);
|
||||
if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id);
|
||||
if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD);
|
||||
// make sure we have a struct with no fields (unit struct)
|
||||
|
|
|
@ -38,7 +38,7 @@ declare_clippy_lint! {
|
|||
/// wait(fut).await;
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.68.0"]
|
||||
#[clippy::version = "1.70.0"]
|
||||
pub LARGE_FUTURES,
|
||||
pedantic,
|
||||
"large future may lead to unexpected stack overflows"
|
||||
|
|
|
@ -38,7 +38,7 @@ impl_lint_pass!(LargeStackArrays => [LARGE_STACK_ARRAYS]);
|
|||
|
||||
impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
|
||||
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
if let ExprKind::Repeat(_, _) = expr.kind
|
||||
if let ExprKind::Repeat(_, _) | ExprKind::Array(_) = expr.kind
|
||||
&& let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).kind()
|
||||
&& let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind()
|
||||
&& let Ok(element_count) = element_count.try_to_target_usize(cx.tcx)
|
||||
|
|
|
@ -17,7 +17,7 @@ declare_clippy_lint! {
|
|||
/// ```rust,ignore
|
||||
/// let my_number = 1;
|
||||
/// ```
|
||||
#[clippy::version = "1.69.0"]
|
||||
#[clippy::version = "1.70.0"]
|
||||
pub LET_WITH_TYPE_UNDERSCORE,
|
||||
complexity,
|
||||
"unneeded underscore type (`_`) in a variable declaration"
|
||||
|
|
|
@ -202,6 +202,7 @@ mod missing_assert_message;
|
|||
mod missing_const_for_fn;
|
||||
mod missing_doc;
|
||||
mod missing_enforced_import_rename;
|
||||
mod missing_fields_in_debug;
|
||||
mod missing_inline;
|
||||
mod missing_trait_methods;
|
||||
mod mixed_read_write_in_expression;
|
||||
|
@ -217,6 +218,7 @@ mod needless_arbitrary_self_type;
|
|||
mod needless_bool;
|
||||
mod needless_borrowed_ref;
|
||||
mod needless_continue;
|
||||
mod needless_else;
|
||||
mod needless_for_each;
|
||||
mod needless_late_init;
|
||||
mod needless_parens_on_range_literals;
|
||||
|
@ -990,6 +992,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
store.register_late_pass(|_| Box::new(items_after_test_module::ItemsAfterTestModule));
|
||||
store.register_early_pass(|| Box::new(ref_patterns::RefPatterns));
|
||||
store.register_late_pass(|_| Box::new(default_constructed_unit_structs::DefaultConstructedUnitStructs));
|
||||
store.register_early_pass(|| Box::new(needless_else::NeedlessElse));
|
||||
store.register_late_pass(|_| Box::new(missing_fields_in_debug::MissingFieldsInDebug));
|
||||
// add lints here, do not remove this comment, it's used in `new_lint`
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,8 @@ struct PathAndSpan {
|
|||
span: Span,
|
||||
}
|
||||
|
||||
/// `MacroRefData` includes the name of the macro.
|
||||
/// `MacroRefData` includes the name of the macro
|
||||
/// and the path from `SourceMap::span_to_filename`.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MacroRefData {
|
||||
name: String,
|
||||
|
|
|
@ -77,53 +77,54 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
|
|||
local.els.is_none() &&
|
||||
local.ty.is_none() &&
|
||||
init.span.ctxt() == stmt.span.ctxt() &&
|
||||
let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init) {
|
||||
match if_let_or_match {
|
||||
IfLetOrMatch::IfLet(if_let_expr, let_pat, if_then, if_else) => if_chain! {
|
||||
if expr_is_simple_identity(let_pat, if_then);
|
||||
if let Some(if_else) = if_else;
|
||||
if expr_diverges(cx, if_else);
|
||||
then {
|
||||
emit_manual_let_else(cx, stmt.span, if_let_expr, local.pat, let_pat, if_else);
|
||||
}
|
||||
},
|
||||
IfLetOrMatch::Match(match_expr, arms, source) => {
|
||||
if self.matches_behaviour == MatchLintBehaviour::Never {
|
||||
return;
|
||||
}
|
||||
if source != MatchSource::Normal {
|
||||
return;
|
||||
}
|
||||
// Any other number than two arms doesn't (necessarily)
|
||||
// have a trivial mapping to let else.
|
||||
if arms.len() != 2 {
|
||||
return;
|
||||
}
|
||||
// Guards don't give us an easy mapping either
|
||||
if arms.iter().any(|arm| arm.guard.is_some()) {
|
||||
return;
|
||||
}
|
||||
let check_types = self.matches_behaviour == MatchLintBehaviour::WellKnownTypes;
|
||||
let diverging_arm_opt = arms
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, arm)| expr_diverges(cx, arm.body) && pat_allowed_for_else(cx, arm.pat, check_types));
|
||||
let Some((idx, diverging_arm)) = diverging_arm_opt else { return; };
|
||||
// If the non-diverging arm is the first one, its pattern can be reused in a let/else statement.
|
||||
// However, if it arrives in second position, its pattern may cover some cases already covered
|
||||
// by the diverging one.
|
||||
// TODO: accept the non-diverging arm as a second position if patterns are disjointed.
|
||||
if idx == 0 {
|
||||
return;
|
||||
}
|
||||
let pat_arm = &arms[1 - idx];
|
||||
if !expr_is_simple_identity(pat_arm.pat, pat_arm.body) {
|
||||
return;
|
||||
}
|
||||
let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init)
|
||||
{
|
||||
match if_let_or_match {
|
||||
IfLetOrMatch::IfLet(if_let_expr, let_pat, if_then, if_else) => if_chain! {
|
||||
if expr_is_simple_identity(let_pat, if_then);
|
||||
if let Some(if_else) = if_else;
|
||||
if expr_diverges(cx, if_else);
|
||||
then {
|
||||
emit_manual_let_else(cx, stmt.span, if_let_expr, local.pat, let_pat, if_else);
|
||||
}
|
||||
},
|
||||
IfLetOrMatch::Match(match_expr, arms, source) => {
|
||||
if self.matches_behaviour == MatchLintBehaviour::Never {
|
||||
return;
|
||||
}
|
||||
if source != MatchSource::Normal {
|
||||
return;
|
||||
}
|
||||
// Any other number than two arms doesn't (necessarily)
|
||||
// have a trivial mapping to let else.
|
||||
if arms.len() != 2 {
|
||||
return;
|
||||
}
|
||||
// Guards don't give us an easy mapping either
|
||||
if arms.iter().any(|arm| arm.guard.is_some()) {
|
||||
return;
|
||||
}
|
||||
let check_types = self.matches_behaviour == MatchLintBehaviour::WellKnownTypes;
|
||||
let diverging_arm_opt = arms
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, arm)| expr_diverges(cx, arm.body) && pat_allowed_for_else(cx, arm.pat, check_types));
|
||||
let Some((idx, diverging_arm)) = diverging_arm_opt else { return; };
|
||||
// If the non-diverging arm is the first one, its pattern can be reused in a let/else statement.
|
||||
// However, if it arrives in second position, its pattern may cover some cases already covered
|
||||
// by the diverging one.
|
||||
// TODO: accept the non-diverging arm as a second position if patterns are disjointed.
|
||||
if idx == 0 {
|
||||
return;
|
||||
}
|
||||
let pat_arm = &arms[1 - idx];
|
||||
if !expr_is_simple_identity(pat_arm.pat, pat_arm.body) {
|
||||
return;
|
||||
}
|
||||
|
||||
emit_manual_let_else(cx, stmt.span, match_expr, local.pat, pat_arm.pat, diverging_arm.body);
|
||||
},
|
||||
}
|
||||
emit_manual_let_else(cx, stmt.span, match_expr, local.pat, pat_arm.pat, diverging_arm.body);
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -145,10 +146,9 @@ fn emit_manual_let_else(
|
|||
"this could be rewritten as `let...else`",
|
||||
|diag| {
|
||||
// This is far from perfect, for example there needs to be:
|
||||
// * mut additions for the bindings
|
||||
// * renamings of the bindings for `PatKind::Or`
|
||||
// * tracking for multi-binding cases: let (foo, bar) = if let (Some(foo), Ok(bar)) = ...
|
||||
// * renamings of the bindings for many `PatKind`s like structs, slices, etc.
|
||||
// * unused binding collision detection with existing ones
|
||||
// * putting patterns with at the top level | inside ()
|
||||
// for this to be machine applicable.
|
||||
let mut app = Applicability::HasPlaceholders;
|
||||
let (sn_expr, _) = snippet_with_context(cx, expr.span, span.ctxt(), "", &mut app);
|
||||
|
@ -159,28 +159,62 @@ fn emit_manual_let_else(
|
|||
} else {
|
||||
format!("{{ {sn_else} }}")
|
||||
};
|
||||
let sn_bl = match pat.kind {
|
||||
PatKind::Or(..) => {
|
||||
let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", &mut app);
|
||||
format!("({sn_pat})")
|
||||
},
|
||||
// Replace the variable name iff `TupleStruct` has one argument like `Variant(v)`.
|
||||
PatKind::TupleStruct(ref w, args, ..) if args.len() == 1 => {
|
||||
let sn_wrapper = cx.sess().source_map().span_to_snippet(w.span()).unwrap_or_default();
|
||||
let (sn_inner, _) = snippet_with_context(cx, local.span, span.ctxt(), "", &mut app);
|
||||
format!("{sn_wrapper}({sn_inner})")
|
||||
},
|
||||
_ => {
|
||||
let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", &mut app);
|
||||
sn_pat.into_owned()
|
||||
},
|
||||
};
|
||||
let sn_bl = replace_in_pattern(cx, span, local, pat, &mut app);
|
||||
let sugg = format!("let {sn_bl} = {sn_expr} else {else_bl};");
|
||||
diag.span_suggestion(span, "consider writing", sugg, app);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// replaces the locals in the pattern
|
||||
fn replace_in_pattern(
|
||||
cx: &LateContext<'_>,
|
||||
span: Span,
|
||||
local: &Pat<'_>,
|
||||
pat: &Pat<'_>,
|
||||
app: &mut Applicability,
|
||||
) -> String {
|
||||
let mut bindings_count = 0;
|
||||
pat.each_binding_or_first(&mut |_, _, _, _| bindings_count += 1);
|
||||
// If the pattern creates multiple bindings, exit early,
|
||||
// as otherwise we might paste the pattern to the positions of multiple bindings.
|
||||
if bindings_count > 1 {
|
||||
let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", app);
|
||||
return sn_pat.into_owned();
|
||||
}
|
||||
|
||||
match pat.kind {
|
||||
PatKind::Binding(..) => {
|
||||
let (sn_bdg, _) = snippet_with_context(cx, local.span, span.ctxt(), "", app);
|
||||
return sn_bdg.to_string();
|
||||
},
|
||||
PatKind::Or(pats) => {
|
||||
let patterns = pats
|
||||
.iter()
|
||||
.map(|pat| replace_in_pattern(cx, span, local, pat, app))
|
||||
.collect::<Vec<_>>();
|
||||
let or_pat = patterns.join(" | ");
|
||||
return format!("({or_pat})");
|
||||
},
|
||||
// Replace the variable name iff `TupleStruct` has one argument like `Variant(v)`.
|
||||
PatKind::TupleStruct(ref w, args, dot_dot_pos) => {
|
||||
let mut args = args
|
||||
.iter()
|
||||
.map(|pat| replace_in_pattern(cx, span, local, pat, app))
|
||||
.collect::<Vec<_>>();
|
||||
if let Some(pos) = dot_dot_pos.as_opt_usize() {
|
||||
args.insert(pos, "..".to_owned());
|
||||
}
|
||||
let args = args.join(", ");
|
||||
let sn_wrapper = cx.sess().source_map().span_to_snippet(w.span()).unwrap_or_default();
|
||||
return format!("{sn_wrapper}({args})");
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", app);
|
||||
sn_pat.into_owned()
|
||||
}
|
||||
|
||||
/// Check whether an expression is divergent. May give false negatives.
|
||||
fn expr_diverges(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
struct V<'cx, 'tcx> {
|
||||
|
|
|
@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_note;
|
|||
use clippy_utils::macros::{is_panic, root_macro_call};
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use clippy_utils::visitors::is_local_used;
|
||||
use clippy_utils::{is_wild, peel_blocks_with_stmt};
|
||||
use clippy_utils::{in_constant, is_wild, peel_blocks_with_stmt};
|
||||
use rustc_hir::{Arm, Expr, PatKind};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
|
@ -10,6 +10,11 @@ use rustc_span::symbol::{kw, sym};
|
|||
use super::MATCH_WILD_ERR_ARM;
|
||||
|
||||
pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<'tcx>]) {
|
||||
// `unwrap`/`expect` is not (yet) const, so we want to allow this in const contexts for now
|
||||
if in_constant(cx, ex.hir_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
let ex_ty = cx.typeck_results().expr_ty(ex).peel_refs();
|
||||
if is_type_diagnostic_item(cx, ex_ty, sym::Result) {
|
||||
for arm in arms {
|
||||
|
|
|
@ -25,7 +25,7 @@ mod wild_in_or_pats;
|
|||
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::source::{snippet_opt, walk_span_to_context};
|
||||
use clippy_utils::{higher, in_constant, is_span_match, tokenize_with_text};
|
||||
use clippy_utils::{higher, in_constant, is_direct_expn_of, is_span_match, tokenize_with_text};
|
||||
use rustc_hir::{Arm, Expr, ExprKind, Local, MatchSource, Pat};
|
||||
use rustc_lexer::TokenKind;
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
|
@ -974,12 +974,16 @@ impl_lint_pass!(Matches => [
|
|||
|
||||
impl<'tcx> LateLintPass<'tcx> for Matches {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if in_external_macro(cx.sess(), expr.span) {
|
||||
if is_direct_expn_of(expr.span, "matches").is_none() && in_external_macro(cx.sess(), expr.span) {
|
||||
return;
|
||||
}
|
||||
let from_expansion = expr.span.from_expansion();
|
||||
|
||||
if let ExprKind::Match(ex, arms, source) = expr.kind {
|
||||
if is_direct_expn_of(expr.span, "matches").is_some() {
|
||||
redundant_pattern_match::check_match(cx, expr, ex, arms);
|
||||
}
|
||||
|
||||
if source == MatchSource::Normal && !is_span_match(cx, expr.span) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use super::REDUNDANT_PATTERN_MATCHING;
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
|
||||
use clippy_utils::source::{snippet, walk_span_to_context};
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::ty::{is_type_diagnostic_item, needs_ordered_drop};
|
||||
use clippy_utils::visitors::any_temporaries_need_ordered_drop;
|
||||
use clippy_utils::{higher, is_trait_method};
|
||||
use clippy_utils::{higher, is_expn_of, is_trait_method};
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::ast::LitKind;
|
||||
use rustc_errors::Applicability;
|
||||
|
@ -190,24 +190,19 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
|
|||
let node_pair = (&arms[0].pat.kind, &arms[1].pat.kind);
|
||||
|
||||
if let Some(good_method) = found_good_method(cx, arms, node_pair) {
|
||||
let span = expr.span.to(op.span);
|
||||
let span = is_expn_of(expr.span, "matches").unwrap_or(expr.span.to(op.span));
|
||||
let result_expr = match &op.kind {
|
||||
ExprKind::AddrOf(_, _, borrowed) => borrowed,
|
||||
_ => op,
|
||||
};
|
||||
span_lint_and_then(
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
REDUNDANT_PATTERN_MATCHING,
|
||||
expr.span,
|
||||
span,
|
||||
&format!("redundant pattern matching, consider using `{good_method}`"),
|
||||
|diag| {
|
||||
diag.span_suggestion(
|
||||
span,
|
||||
"try this",
|
||||
format!("{}.{good_method}", snippet(cx, result_expr.span, "_")),
|
||||
Applicability::MaybeIncorrect, // snippet
|
||||
);
|
||||
},
|
||||
"try this",
|
||||
format!("{}.{good_method}", snippet(cx, result_expr.span, "_")),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use rustc_errors::Applicability;
|
|||
use rustc_hir as hir;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::symbol::{Symbol, sym};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
|
||||
use super::INEFFICIENT_TO_STRING;
|
||||
|
||||
|
|
|
@ -3191,7 +3191,7 @@ declare_clippy_lint! {
|
|||
/// let mut v = vec![1, 2, 3];
|
||||
/// v.clear();
|
||||
/// ```
|
||||
#[clippy::version = "1.69.0"]
|
||||
#[clippy::version = "1.70.0"]
|
||||
pub CLEAR_WITH_DRAIN,
|
||||
nursery,
|
||||
"calling `drain` in order to `clear` a container"
|
||||
|
|
|
@ -36,7 +36,7 @@ declare_clippy_lint! {
|
|||
/// assert!(service.ready, "`service.poll_ready()` must be called first to ensure that service is ready to receive requests");
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.69.0"]
|
||||
#[clippy::version = "1.70.0"]
|
||||
pub MISSING_ASSERT_MESSAGE,
|
||||
restriction,
|
||||
"checks assertions without a custom panic message"
|
||||
|
|
234
clippy_lints/src/missing_fields_in_debug.rs
Normal file
234
clippy_lints/src/missing_fields_in_debug.rs
Normal file
|
@ -0,0 +1,234 @@
|
|||
use std::ops::ControlFlow;
|
||||
|
||||
use clippy_utils::{
|
||||
diagnostics::span_lint_and_then,
|
||||
is_path_lang_item, paths,
|
||||
ty::match_type,
|
||||
visitors::{for_each_expr, Visitable},
|
||||
};
|
||||
use rustc_ast::LitKind;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir::Block;
|
||||
use rustc_hir::{
|
||||
def::{DefKind, Res},
|
||||
Expr, ImplItemKind, LangItem, Node,
|
||||
};
|
||||
use rustc_hir::{ExprKind, Impl, ItemKind, QPath, TyKind};
|
||||
use rustc_hir::{ImplItem, Item, VariantData};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::TypeckResults;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::{sym, Span, Symbol};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for manual [`core::fmt::Debug`](https://doc.rust-lang.org/core/fmt/trait.Debug.html) implementations that do not use all fields.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// A common mistake is to forget to update manual `Debug` implementations when adding a new field
|
||||
/// to a struct or a new variant to an enum.
|
||||
///
|
||||
/// At the same time, it also acts as a style lint to suggest using [`core::fmt::DebugStruct::finish_non_exhaustive`](https://doc.rust-lang.org/core/fmt/struct.DebugStruct.html#method.finish_non_exhaustive)
|
||||
/// for the times when the user intentionally wants to leave out certain fields (e.g. to hide implementation details).
|
||||
///
|
||||
/// ### Known problems
|
||||
/// This lint works based on the `DebugStruct` helper types provided by the `Formatter`,
|
||||
/// so this won't detect `Debug` impls that use the `write!` macro.
|
||||
/// Oftentimes there is more logic to a `Debug` impl if it uses `write!` macro, so it tries
|
||||
/// to be on the conservative side and not lint in those cases in an attempt to prevent false positives.
|
||||
///
|
||||
/// This lint also does not look through function calls, so calling a function does not consider fields
|
||||
/// used inside of that function as used by the `Debug` impl.
|
||||
///
|
||||
/// Lastly, it also ignores tuple structs as their `DebugTuple` formatter does not have a `finish_non_exhaustive`
|
||||
/// method, as well as enums because their exhaustiveness is already checked by the compiler when matching on the enum,
|
||||
/// making it much less likely to accidentally forget to update the `Debug` impl when adding a new variant.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
/// use std::fmt;
|
||||
/// struct Foo {
|
||||
/// data: String,
|
||||
/// // implementation detail
|
||||
/// hidden_data: i32
|
||||
/// }
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// formatter
|
||||
/// .debug_struct("Foo")
|
||||
/// .field("data", &self.data)
|
||||
/// .finish()
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// use std::fmt;
|
||||
/// struct Foo {
|
||||
/// data: String,
|
||||
/// // implementation detail
|
||||
/// hidden_data: i32
|
||||
/// }
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// formatter
|
||||
/// .debug_struct("Foo")
|
||||
/// .field("data", &self.data)
|
||||
/// .finish_non_exhaustive()
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.70.0"]
|
||||
pub MISSING_FIELDS_IN_DEBUG,
|
||||
pedantic,
|
||||
"missing fields in manual `Debug` implementation"
|
||||
}
|
||||
declare_lint_pass!(MissingFieldsInDebug => [MISSING_FIELDS_IN_DEBUG]);
|
||||
|
||||
fn report_lints(cx: &LateContext<'_>, span: Span, span_notes: Vec<(Span, &'static str)>) {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
MISSING_FIELDS_IN_DEBUG,
|
||||
span,
|
||||
"manual `Debug` impl does not include all fields",
|
||||
|diag| {
|
||||
for (span, note) in span_notes {
|
||||
diag.span_note(span, note);
|
||||
}
|
||||
diag.help("consider including all fields in this `Debug` impl")
|
||||
.help("consider calling `.finish_non_exhaustive()` if you intend to ignore fields");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Checks if we should lint in a block of code
|
||||
///
|
||||
/// The way we check for this condition is by checking if there is
|
||||
/// a call to `Formatter::debug_struct` but no call to `.finish_non_exhaustive()`.
|
||||
fn should_lint<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
typeck_results: &TypeckResults<'tcx>,
|
||||
block: impl Visitable<'tcx>,
|
||||
) -> bool {
|
||||
// Is there a call to `DebugStruct::finish_non_exhaustive`? Don't lint if there is.
|
||||
let mut has_finish_non_exhaustive = false;
|
||||
// Is there a call to `DebugStruct::debug_struct`? Do lint if there is.
|
||||
let mut has_debug_struct = false;
|
||||
|
||||
for_each_expr(block, |expr| {
|
||||
if let ExprKind::MethodCall(path, recv, ..) = &expr.kind {
|
||||
let recv_ty = typeck_results.expr_ty(recv).peel_refs();
|
||||
|
||||
if path.ident.name == sym::debug_struct && match_type(cx, recv_ty, &paths::FORMATTER) {
|
||||
has_debug_struct = true;
|
||||
} else if path.ident.name == sym!(finish_non_exhaustive) && match_type(cx, recv_ty, &paths::DEBUG_STRUCT) {
|
||||
has_finish_non_exhaustive = true;
|
||||
}
|
||||
}
|
||||
ControlFlow::<!, _>::Continue(())
|
||||
});
|
||||
|
||||
!has_finish_non_exhaustive && has_debug_struct
|
||||
}
|
||||
|
||||
/// Checks if the given expression is a call to `DebugStruct::field`
|
||||
/// and the first argument to it is a string literal and if so, returns it
|
||||
///
|
||||
/// Example: `.field("foo", ....)` returns `Some("foo")`
|
||||
fn as_field_call<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
typeck_results: &TypeckResults<'tcx>,
|
||||
expr: &Expr<'_>,
|
||||
) -> Option<Symbol> {
|
||||
if let ExprKind::MethodCall(path, recv, [debug_field, _], _) = &expr.kind
|
||||
&& let recv_ty = typeck_results.expr_ty(recv).peel_refs()
|
||||
&& match_type(cx, recv_ty, &paths::DEBUG_STRUCT)
|
||||
&& path.ident.name == sym::field
|
||||
&& let ExprKind::Lit(lit) = &debug_field.kind
|
||||
&& let LitKind::Str(sym, ..) = lit.node
|
||||
{
|
||||
Some(sym)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to find unused fields assuming that the item is a struct
|
||||
fn check_struct<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
typeck_results: &TypeckResults<'tcx>,
|
||||
block: &'tcx Block<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
item: &'tcx Item<'tcx>,
|
||||
data: &VariantData<'_>,
|
||||
) {
|
||||
// Is there a "direct" field access anywhere (i.e. self.foo)?
|
||||
// We don't want to lint if there is not, because the user might have
|
||||
// a newtype struct and use fields from the wrapped type only.
|
||||
let mut has_direct_field_access = false;
|
||||
let mut field_accesses = FxHashSet::default();
|
||||
|
||||
for_each_expr(block, |expr| {
|
||||
if let ExprKind::Field(target, ident) = expr.kind
|
||||
&& let target_ty = typeck_results.expr_ty_adjusted(target).peel_refs()
|
||||
&& target_ty == self_ty
|
||||
{
|
||||
field_accesses.insert(ident.name);
|
||||
has_direct_field_access = true;
|
||||
} else if let Some(sym) = as_field_call(cx, typeck_results, expr) {
|
||||
field_accesses.insert(sym);
|
||||
}
|
||||
ControlFlow::<!, _>::Continue(())
|
||||
});
|
||||
|
||||
let span_notes = data
|
||||
.fields()
|
||||
.iter()
|
||||
.filter_map(|field| {
|
||||
if field_accesses.contains(&field.ident.name) || is_path_lang_item(cx, field.ty, LangItem::PhantomData) {
|
||||
None
|
||||
} else {
|
||||
Some((field.span, "this field is unused"))
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// only lint if there's also at least one direct field access to allow patterns
|
||||
// where one might have a newtype struct and uses fields from the wrapped type
|
||||
if !span_notes.is_empty() && has_direct_field_access {
|
||||
report_lints(cx, item.span, span_notes);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx rustc_hir::Item<'tcx>) {
|
||||
// is this an `impl Debug for X` block?
|
||||
if let ItemKind::Impl(Impl { of_trait: Some(trait_ref), self_ty, items, .. }) = item.kind
|
||||
&& let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res
|
||||
&& let TyKind::Path(QPath::Resolved(_, self_path)) = &self_ty.kind
|
||||
&& cx.match_def_path(trait_def_id, &[sym::core, sym::fmt, sym::Debug])
|
||||
// don't trigger if this impl was derived
|
||||
&& !cx.tcx.has_attr(item.owner_id, sym::automatically_derived)
|
||||
&& !item.span.from_expansion()
|
||||
// find `Debug::fmt` function
|
||||
&& let Some(fmt_item) = items.iter().find(|i| i.ident.name == sym::fmt)
|
||||
&& let ImplItem { kind: ImplItemKind::Fn(_, body_id), .. } = cx.tcx.hir().impl_item(fmt_item.id)
|
||||
&& let body = cx.tcx.hir().body(*body_id)
|
||||
&& let ExprKind::Block(block, _) = body.value.kind
|
||||
// inspect `self`
|
||||
&& let self_ty = cx.tcx.type_of(self_path.res.def_id()).skip_binder().peel_refs()
|
||||
&& let Some(self_adt) = self_ty.ty_adt_def()
|
||||
&& let Some(self_def_id) = self_adt.did().as_local()
|
||||
&& let Some(Node::Item(self_item)) = cx.tcx.hir().find_by_def_id(self_def_id)
|
||||
// NB: can't call cx.typeck_results() as we are not in a body
|
||||
&& let typeck_results = cx.tcx.typeck_body(*body_id)
|
||||
&& should_lint(cx, typeck_results, block)
|
||||
{
|
||||
// we intentionally only lint structs, see lint description
|
||||
if let ItemKind::Struct(data, _) = &self_item.kind {
|
||||
check_struct(cx, typeck_results, block, self_ty, item, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -92,10 +92,6 @@ impl<'a, 'tcx> Visitor<'tcx> for MutArgVisitor<'a, 'tcx> {
|
|||
self.found = true;
|
||||
return;
|
||||
},
|
||||
ExprKind::If(..) => {
|
||||
self.found = true;
|
||||
return;
|
||||
},
|
||||
ExprKind::Path(_) => {
|
||||
if let Some(adj) = self.cx.typeck_results().adjustments().get(expr.hir_id) {
|
||||
if adj
|
||||
|
|
61
clippy_lints/src/needless_else.rs
Normal file
61
clippy_lints/src/needless_else.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::{diagnostics::span_lint_and_sugg, source::trim_span};
|
||||
use rustc_ast::ast::{Expr, ExprKind};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for empty `else` branches.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// An empty else branch does nothing and can be removed.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
///# fn check() -> bool { true }
|
||||
/// if check() {
|
||||
/// println!("Check successful!");
|
||||
/// } else {
|
||||
/// }
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
///# fn check() -> bool { true }
|
||||
/// if check() {
|
||||
/// println!("Check successful!");
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.71.0"]
|
||||
pub NEEDLESS_ELSE,
|
||||
style,
|
||||
"empty else branch"
|
||||
}
|
||||
declare_lint_pass!(NeedlessElse => [NEEDLESS_ELSE]);
|
||||
|
||||
impl EarlyLintPass for NeedlessElse {
|
||||
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
|
||||
if let ExprKind::If(_, then_block, Some(else_clause)) = &expr.kind
|
||||
&& let ExprKind::Block(block, _) = &else_clause.kind
|
||||
&& !expr.span.from_expansion()
|
||||
&& !else_clause.span.from_expansion()
|
||||
&& block.stmts.is_empty()
|
||||
&& let Some(trimmed) = expr.span.trim_start(then_block.span)
|
||||
&& let span = trim_span(cx.sess().source_map(), trimmed)
|
||||
&& let Some(else_snippet) = snippet_opt(cx, span)
|
||||
// Ignore else blocks that contain comments or #[cfg]s
|
||||
&& !else_snippet.contains(['/', '#'])
|
||||
{
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
NEEDLESS_ELSE,
|
||||
span,
|
||||
"this else branch is empty",
|
||||
"you can remove it",
|
||||
String::new(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,7 +35,7 @@ declare_clippy_lint! {
|
|||
/// };
|
||||
/// let fut = f;
|
||||
/// ```
|
||||
#[clippy::version = "1.69.0"]
|
||||
#[clippy::version = "1.70.0"]
|
||||
pub REDUNDANT_ASYNC_BLOCK,
|
||||
complexity,
|
||||
"`async { future.await }` can be replaced by `future`"
|
||||
|
|
|
@ -177,7 +177,7 @@ fn check_set<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
|
|||
}
|
||||
|
||||
fn check_regex<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
|
||||
let mut parser = regex_syntax::ParserBuilder::new().unicode(true).utf8(!utf8).build();
|
||||
let mut parser = regex_syntax::ParserBuilder::new().unicode(true).utf8(utf8).build();
|
||||
|
||||
if let ExprKind::Lit(lit) = expr.kind {
|
||||
if let LitKind::Str(ref r, style) = lit.node {
|
||||
|
|
|
@ -70,7 +70,7 @@ declare_clippy_lint! {
|
|||
"using a return statement like `return expr;` where an expression would suffice"
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum RetReplacement<'tcx> {
|
||||
Empty,
|
||||
Block,
|
||||
|
@ -80,7 +80,7 @@ enum RetReplacement<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> RetReplacement<'tcx> {
|
||||
fn sugg_help(self) -> &'static str {
|
||||
fn sugg_help(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Empty | Self::Expr(..) => "remove `return`",
|
||||
Self::Block => "replace `return` with an empty block",
|
||||
|
@ -88,10 +88,11 @@ impl<'tcx> RetReplacement<'tcx> {
|
|||
Self::IfSequence(..) => "remove `return` and wrap the sequence with parentheses",
|
||||
}
|
||||
}
|
||||
fn applicability(&self) -> Option<Applicability> {
|
||||
|
||||
fn applicability(&self) -> Applicability {
|
||||
match self {
|
||||
Self::Expr(_, ap) | Self::IfSequence(_, ap) => Some(*ap),
|
||||
_ => None,
|
||||
Self::Expr(_, ap) | Self::IfSequence(_, ap) => *ap,
|
||||
_ => Applicability::MachineApplicable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -271,7 +272,7 @@ fn check_final_expr<'tcx>(
|
|||
return;
|
||||
}
|
||||
|
||||
emit_return_lint(cx, ret_span, semi_spans, replacement);
|
||||
emit_return_lint(cx, ret_span, semi_spans, &replacement);
|
||||
},
|
||||
ExprKind::If(_, then, else_clause_opt) => {
|
||||
check_block_return(cx, &then.kind, peeled_drop_expr.span, semi_spans.clone());
|
||||
|
@ -306,20 +307,17 @@ fn expr_contains_conjunctive_ifs<'tcx>(expr: &'tcx Expr<'tcx>) -> bool {
|
|||
contains_if(expr, false)
|
||||
}
|
||||
|
||||
fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, semi_spans: Vec<Span>, replacement: RetReplacement<'_>) {
|
||||
fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, semi_spans: Vec<Span>, replacement: &RetReplacement<'_>) {
|
||||
if ret_span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
|
||||
let applicability = replacement.applicability().unwrap_or(Applicability::MachineApplicable);
|
||||
let return_replacement = replacement.to_string();
|
||||
let sugg_help = replacement.sugg_help();
|
||||
span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded `return` statement", |diag| {
|
||||
diag.span_suggestion_hidden(ret_span, sugg_help, return_replacement, applicability);
|
||||
// for each parent statement, we need to remove the semicolon
|
||||
for semi_stmt_span in semi_spans {
|
||||
diag.tool_only_span_suggestion(semi_stmt_span, "remove this semicolon", "", applicability);
|
||||
}
|
||||
let suggestions = std::iter::once((ret_span, replacement.to_string()))
|
||||
.chain(semi_spans.into_iter().map(|span| (span, String::new())))
|
||||
.collect();
|
||||
|
||||
diag.multipart_suggestion_verbose(replacement.sugg_help(), suggestions, replacement.applicability());
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -55,11 +55,11 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
|
|||
if matches!(cx.tcx.def_kind(id.owner_id), DefKind::Impl { .. })
|
||||
&& let item = cx.tcx.hir().item(id)
|
||||
&& let ItemKind::Impl(Impl {
|
||||
items,
|
||||
of_trait,
|
||||
self_ty,
|
||||
..
|
||||
}) = &item.kind
|
||||
items,
|
||||
of_trait,
|
||||
self_ty,
|
||||
..
|
||||
}) = &item.kind
|
||||
&& let TyKind::Path(QPath::Resolved(_, Path { res, .. })) = self_ty.kind
|
||||
{
|
||||
if !map.contains_key(res) {
|
||||
|
|
|
@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sug
|
|||
use clippy_utils::source::{snippet, snippet_with_applicability};
|
||||
use clippy_utils::ty::is_type_lang_item;
|
||||
use clippy_utils::{get_expr_use_or_unification_node, peel_blocks, SpanlessEq};
|
||||
use clippy_utils::{get_parent_expr, is_lint_allowed, match_function_call, method_calls, paths};
|
||||
use clippy_utils::{get_parent_expr, is_lint_allowed, is_path_diagnostic_item, method_calls};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
@ -255,7 +255,8 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
|
|||
|
||||
if_chain! {
|
||||
// Find std::str::converts::from_utf8
|
||||
if let Some(args) = match_function_call(cx, e, &paths::STR_FROM_UTF8);
|
||||
if let ExprKind::Call(fun, args) = e.kind;
|
||||
if is_path_diagnostic_item(cx, fun, sym::str_from_utf8);
|
||||
|
||||
// Find string::as_bytes
|
||||
if let ExprKind::AddrOf(BorrowKind::Ref, _, args) = args[0].kind;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use rustc_hir::intravisit::{walk_body, walk_expr, walk_fn, FnKind, Visitor};
|
||||
use rustc_hir::{Body, Expr, ExprKind, FnDecl, YieldSource};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
|
@ -42,6 +42,10 @@ declare_lint_pass!(UnusedAsync => [UNUSED_ASYNC]);
|
|||
struct AsyncFnVisitor<'a, 'tcx> {
|
||||
cx: &'a LateContext<'tcx>,
|
||||
found_await: bool,
|
||||
/// Also keep track of `await`s in nested async blocks so we can mention
|
||||
/// it in a note
|
||||
await_in_async_block: Option<Span>,
|
||||
async_depth: usize,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Visitor<'tcx> for AsyncFnVisitor<'a, 'tcx> {
|
||||
|
@ -49,7 +53,11 @@ impl<'a, 'tcx> Visitor<'tcx> for AsyncFnVisitor<'a, 'tcx> {
|
|||
|
||||
fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
|
||||
if let ExprKind::Yield(_, YieldSource::Await { .. }) = ex.kind {
|
||||
self.found_await = true;
|
||||
if self.async_depth == 1 {
|
||||
self.found_await = true;
|
||||
} else if self.await_in_async_block.is_none() {
|
||||
self.await_in_async_block = Some(ex.span);
|
||||
}
|
||||
}
|
||||
walk_expr(self, ex);
|
||||
}
|
||||
|
@ -57,6 +65,20 @@ impl<'a, 'tcx> Visitor<'tcx> for AsyncFnVisitor<'a, 'tcx> {
|
|||
fn nested_visit_map(&mut self) -> Self::Map {
|
||||
self.cx.tcx.hir()
|
||||
}
|
||||
|
||||
fn visit_body(&mut self, b: &'tcx Body<'tcx>) {
|
||||
let is_async_block = matches!(b.generator_kind, Some(rustc_hir::GeneratorKind::Async(_)));
|
||||
|
||||
if is_async_block {
|
||||
self.async_depth += 1;
|
||||
}
|
||||
|
||||
walk_body(self, b);
|
||||
|
||||
if is_async_block {
|
||||
self.async_depth -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for UnusedAsync {
|
||||
|
@ -70,16 +92,30 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAsync {
|
|||
def_id: LocalDefId,
|
||||
) {
|
||||
if !span.from_expansion() && fn_kind.asyncness().is_async() {
|
||||
let mut visitor = AsyncFnVisitor { cx, found_await: false };
|
||||
let mut visitor = AsyncFnVisitor {
|
||||
cx,
|
||||
found_await: false,
|
||||
async_depth: 0,
|
||||
await_in_async_block: None,
|
||||
};
|
||||
walk_fn(&mut visitor, fn_kind, fn_decl, body.id(), def_id);
|
||||
if !visitor.found_await {
|
||||
span_lint_and_help(
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
UNUSED_ASYNC,
|
||||
span,
|
||||
"unused `async` for function with no await statements",
|
||||
None,
|
||||
"consider removing the `async` from this function",
|
||||
|diag| {
|
||||
diag.help("consider removing the `async` from this function");
|
||||
|
||||
if let Some(span) = visitor.await_in_async_block {
|
||||
diag.span_note(
|
||||
span,
|
||||
"`await` used in an async block, which does not require \
|
||||
the enclosing function to be `async`",
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -486,7 +486,7 @@ pub fn lookup_conf_file() -> io::Result<(Option<PathBuf>, Vec<String>)> {
|
|||
const CONFIG_FILE_NAMES: [&str; 2] = [".clippy.toml", "clippy.toml"];
|
||||
|
||||
// Start looking for a config file in CLIPPY_CONF_DIR, or failing that, CARGO_MANIFEST_DIR.
|
||||
// If neither of those exist, use ".".
|
||||
// If neither of those exist, use ".". (Update documentation if this priority changes)
|
||||
let mut current = env::var_os("CLIPPY_CONF_DIR")
|
||||
.or_else(|| env::var_os("CARGO_MANIFEST_DIR"))
|
||||
.map_or_else(|| PathBuf::from("."), PathBuf::from)
|
||||
|
|
|
@ -65,8 +65,9 @@ declare_clippy_lint! {
|
|||
/// This can lead to confusing error messages at best and to unexpected behavior at worst.
|
||||
///
|
||||
/// ### Exceptions
|
||||
/// Wildcard imports are allowed from modules named `prelude`. Many crates (including the standard library)
|
||||
/// provide modules named "prelude" specifically designed for wildcard import.
|
||||
/// Wildcard imports are allowed from modules that their name contains `prelude`. Many crates
|
||||
/// (including the standard library) provide modules named "prelude" specifically designed
|
||||
/// for wildcard import.
|
||||
///
|
||||
/// `use super::*` is allowed in test modules. This is defined as any module with "test" in the name.
|
||||
///
|
||||
|
@ -212,7 +213,9 @@ impl WildcardImports {
|
|||
// Allow "...prelude::..::*" imports.
|
||||
// Many crates have a prelude, and it is imported as a glob by design.
|
||||
fn is_prelude_import(segments: &[PathSegment<'_>]) -> bool {
|
||||
segments.iter().any(|ps| ps.ident.name == sym::prelude)
|
||||
segments
|
||||
.iter()
|
||||
.any(|ps| ps.ident.name.as_str().contains(sym::prelude.as_str()))
|
||||
}
|
||||
|
||||
// Allow "super::*" imports in tests.
|
||||
|
|
|
@ -83,9 +83,9 @@ pub fn span_lint_and_help<T: LintContext>(
|
|||
cx.struct_span_lint(lint, span, msg.to_string(), |diag| {
|
||||
let help = help.to_string();
|
||||
if let Some(help_span) = help_span {
|
||||
diag.span_help(help_span, help.to_string());
|
||||
diag.span_help(help_span, help);
|
||||
} else {
|
||||
diag.help(help.to_string());
|
||||
diag.help(help);
|
||||
}
|
||||
docs_link(diag, lint);
|
||||
diag
|
||||
|
|
|
@ -287,7 +287,7 @@ pub fn is_wild(pat: &Pat<'_>) -> bool {
|
|||
/// Checks if the given `QPath` belongs to a type alias.
|
||||
pub fn is_ty_alias(qpath: &QPath<'_>) -> bool {
|
||||
match *qpath {
|
||||
QPath::Resolved(_, path) => matches!(path.res, Res::Def(DefKind::TyAlias, ..)),
|
||||
QPath::Resolved(_, path) => matches!(path.res, Res::Def(DefKind::TyAlias | DefKind::AssocTy, ..)),
|
||||
QPath::TypeRelative(ty, _) if let TyKind::Path(qpath) = ty.kind => { is_ty_alias(&qpath) },
|
||||
_ => false,
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ macro_rules! msrv_aliases {
|
|||
// names may refer to stabilized feature flags or library items
|
||||
msrv_aliases! {
|
||||
1,68,0 { PATH_MAIN_SEPARATOR_STR }
|
||||
1,65,0 { LET_ELSE }
|
||||
1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS }
|
||||
1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE }
|
||||
1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY }
|
||||
1,55,0 { SEEK_REWIND }
|
||||
|
|
|
@ -125,8 +125,6 @@ pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"];
|
|||
pub const STR_BYTES: [&str; 4] = ["core", "str", "<impl str>", "bytes"];
|
||||
pub const STR_CHARS: [&str; 4] = ["core", "str", "<impl str>", "chars"];
|
||||
pub const STR_ENDS_WITH: [&str; 4] = ["core", "str", "<impl str>", "ends_with"];
|
||||
pub const STR_FROM_UTF8: [&str; 4] = ["core", "str", "converts", "from_utf8"];
|
||||
pub const STR_FROM_UTF8_UNCHECKED: [&str; 4] = ["core", "str", "converts", "from_utf8_unchecked"];
|
||||
pub const STR_LEN: [&str; 4] = ["core", "str", "<impl str>", "len"];
|
||||
pub const STR_STARTS_WITH: [&str; 4] = ["core", "str", "<impl str>", "starts_with"];
|
||||
#[cfg(feature = "internal")]
|
||||
|
@ -163,3 +161,5 @@ pub const VEC_IS_EMPTY: [&str; 4] = ["alloc", "vec", "Vec", "is_empty"];
|
|||
pub const VEC_POP: [&str; 4] = ["alloc", "vec", "Vec", "pop"];
|
||||
pub const OPTION_UNWRAP: [&str; 4] = ["core", "option", "Option", "unwrap"];
|
||||
pub const OPTION_EXPECT: [&str; 4] = ["core", "option", "Option", "expect"];
|
||||
pub const FORMATTER: [&str; 3] = ["core", "fmt", "Formatter"];
|
||||
pub const DEBUG_STRUCT: [&str; 4] = ["core", "fmt", "builders", "DebugStruct"];
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_hir::{BlockCheckMode, Expr, ExprKind, UnsafeSource};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::{original_sp, SourceMap};
|
||||
|
@ -71,11 +71,16 @@ pub fn expr_block<T: LintContext>(
|
|||
app: &mut Applicability,
|
||||
) -> String {
|
||||
let (code, from_macro) = snippet_block_with_context(cx, expr.span, outer, default, indent_relative_to, app);
|
||||
if from_macro {
|
||||
format!("{{ {code} }}")
|
||||
} else if let ExprKind::Block(_, _) = expr.kind {
|
||||
if !from_macro &&
|
||||
let ExprKind::Block(block, _) = expr.kind &&
|
||||
block.rules != BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided)
|
||||
{
|
||||
format!("{code}")
|
||||
} else {
|
||||
// FIXME: add extra indent for the unsafe blocks:
|
||||
// original code: unsafe { ... }
|
||||
// result code: { unsafe { ... } }
|
||||
// desired code: {\n unsafe { ... }\n}
|
||||
format!("{{ {code} }}")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.11.0"
|
||||
|
@ -9,71 +11,14 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "ctrlc"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "653abc99aa905f693d89df4797fadc08085baee379db92be9f2496cefe8a6f2c"
|
||||
dependencies = [
|
||||
"kernel32-sys",
|
||||
"nix",
|
||||
"winapi 0.2.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
dependencies = [
|
||||
"winapi 0.2.8",
|
||||
"winapi-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
|
||||
|
||||
[[package]]
|
||||
name = "multiple_crate_versions"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"ctrlc",
|
||||
"winapi 0.2.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2c5afeb0198ec7be8569d666644b574345aad2e95a53baf3a532da3e0f3fb32"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.8"
|
||||
|
@ -90,12 +35,6 @@ dependencies = [
|
|||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-build"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
|
|
|
@ -6,5 +6,5 @@ publish = false
|
|||
[workspace]
|
||||
|
||||
[dependencies]
|
||||
ctrlc = "=3.1.0"
|
||||
winapi = "0.2"
|
||||
ansi_term = "=0.11.0"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//@normalize-stderr-test: "produce_ice.rs:\d*:\d*" -> "produce_ice.rs"
|
||||
//@normalize-stderr-test: "', .*clippy_lints" -> "', clippy_lints"
|
||||
//@normalize-stderr-test: "'rustc'" -> "'<unnamed>'"
|
||||
//@normalize-stderr-test: "running on .*" -> "running on <target>"
|
||||
//@normalize-stderr-test: "rustc 1\.\d+.* running on .*" -> "rustc <version> running on <target>"
|
||||
//@normalize-stderr-test: "(?ms)query stack during panic:\n.*end of query stack\n" -> ""
|
||||
|
||||
#![deny(clippy::internal)]
|
||||
|
|
|
@ -5,10 +5,9 @@ error: the compiler unexpectedly panicked. this is a bug.
|
|||
|
||||
note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new
|
||||
|
||||
note: rustc 1.71.0-nightly (521f4dae1 2023-05-19) running on <target>
|
||||
note: rustc <version> running on <target>
|
||||
|
||||
note: compiler flags: -C prefer-dynamic -Z ui-testing
|
||||
|
||||
note: Clippy version: foo
|
||||
|
||||
thread panicked while panicking. aborting.
|
||||
query stack during panic:
|
||||
thread panicked while processing panic. aborting.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![warn(clippy::ifs_same_cond)]
|
||||
#![allow(clippy::if_same_then_else, clippy::comparison_chain)]
|
||||
#![allow(clippy::if_same_then_else, clippy::comparison_chain, clippy::needless_else)]
|
||||
|
||||
fn main() {}
|
||||
|
||||
|
|
|
@ -25,3 +25,9 @@ pub mod prelude {
|
|||
pub struct PreludeModAnywhere;
|
||||
}
|
||||
}
|
||||
|
||||
pub mod extern_prelude {
|
||||
pub mod v1 {
|
||||
pub struct ExternPreludeModAnywhere;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#![deny(clippy::branches_sharing_code, clippy::if_same_then_else)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(clippy::mixed_read_write_in_expression, clippy::uninlined_format_args)]
|
||||
#![allow(
|
||||
clippy::mixed_read_write_in_expression,
|
||||
clippy::uninlined_format_args,
|
||||
clippy::needless_else
|
||||
)]
|
||||
|
||||
// This tests valid if blocks that shouldn't trigger the lint
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: this `if` has identical blocks
|
||||
--> $DIR/valid_if_blocks.rs:105:14
|
||||
--> $DIR/valid_if_blocks.rs:109:14
|
||||
|
|
||||
LL | if false {
|
||||
| ______________^
|
||||
|
@ -7,7 +7,7 @@ LL | | } else {
|
|||
| |_____^
|
||||
|
|
||||
note: same as this
|
||||
--> $DIR/valid_if_blocks.rs:106:12
|
||||
--> $DIR/valid_if_blocks.rs:110:12
|
||||
|
|
||||
LL | } else {
|
||||
| ____________^
|
||||
|
@ -20,7 +20,7 @@ LL | #![deny(clippy::branches_sharing_code, clippy::if_same_then_else)]
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: this `if` has identical blocks
|
||||
--> $DIR/valid_if_blocks.rs:116:15
|
||||
--> $DIR/valid_if_blocks.rs:120:15
|
||||
|
|
||||
LL | if x == 0 {
|
||||
| _______________^
|
||||
|
@ -31,7 +31,7 @@ LL | | } else {
|
|||
| |_____^
|
||||
|
|
||||
note: same as this
|
||||
--> $DIR/valid_if_blocks.rs:120:12
|
||||
--> $DIR/valid_if_blocks.rs:124:12
|
||||
|
|
||||
LL | } else {
|
||||
| ____________^
|
||||
|
@ -42,19 +42,19 @@ LL | | }
|
|||
| |_____^
|
||||
|
||||
error: this `if` has identical blocks
|
||||
--> $DIR/valid_if_blocks.rs:127:23
|
||||
--> $DIR/valid_if_blocks.rs:131:23
|
||||
|
|
||||
LL | let _ = if x == 6 { 7 } else { 7 };
|
||||
| ^^^^^
|
||||
|
|
||||
note: same as this
|
||||
--> $DIR/valid_if_blocks.rs:127:34
|
||||
--> $DIR/valid_if_blocks.rs:131:34
|
||||
|
|
||||
LL | let _ = if x == 6 { 7 } else { 7 };
|
||||
| ^^^^^
|
||||
|
||||
error: this `if` has identical blocks
|
||||
--> $DIR/valid_if_blocks.rs:133:23
|
||||
--> $DIR/valid_if_blocks.rs:137:23
|
||||
|
|
||||
LL | } else if x == 68 {
|
||||
| _______________________^
|
||||
|
@ -66,7 +66,7 @@ LL | | } else {
|
|||
| |_____^
|
||||
|
|
||||
note: same as this
|
||||
--> $DIR/valid_if_blocks.rs:138:12
|
||||
--> $DIR/valid_if_blocks.rs:142:12
|
||||
|
|
||||
LL | } else {
|
||||
| ____________^
|
||||
|
@ -78,7 +78,7 @@ LL | | };
|
|||
| |_____^
|
||||
|
||||
error: this `if` has identical blocks
|
||||
--> $DIR/valid_if_blocks.rs:147:23
|
||||
--> $DIR/valid_if_blocks.rs:151:23
|
||||
|
|
||||
LL | } else if x == 68 {
|
||||
| _______________________^
|
||||
|
@ -88,7 +88,7 @@ LL | | } else {
|
|||
| |_____^
|
||||
|
|
||||
note: same as this
|
||||
--> $DIR/valid_if_blocks.rs:150:12
|
||||
--> $DIR/valid_if_blocks.rs:154:12
|
||||
|
|
||||
LL | } else {
|
||||
| ____________^
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#![no_std]
|
||||
#![allow(clippy::if_same_then_else)]
|
||||
#![allow(clippy::redundant_pattern_matching)]
|
||||
#![allow(clippy::needless_else)]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
|
|
|
@ -101,6 +101,28 @@ struct EmptyStruct {}
|
|||
#[non_exhaustive]
|
||||
struct NonExhaustiveStruct;
|
||||
|
||||
mod issue_10755 {
|
||||
struct Sqlite {}
|
||||
|
||||
trait HasArguments<'q> {
|
||||
type Arguments;
|
||||
}
|
||||
|
||||
impl<'q> HasArguments<'q> for Sqlite {
|
||||
type Arguments = std::marker::PhantomData<&'q ()>;
|
||||
}
|
||||
|
||||
type SqliteArguments<'q> = <Sqlite as HasArguments<'q>>::Arguments;
|
||||
|
||||
fn foo() {
|
||||
// should not lint
|
||||
// type alias cannot be used as a constructor
|
||||
let _ = <Sqlite as HasArguments>::Arguments::default();
|
||||
|
||||
let _ = SqliteArguments::default();
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// should lint
|
||||
let _ = PhantomData::<usize>;
|
||||
|
|
|
@ -101,6 +101,28 @@ struct EmptyStruct {}
|
|||
#[non_exhaustive]
|
||||
struct NonExhaustiveStruct;
|
||||
|
||||
mod issue_10755 {
|
||||
struct Sqlite {}
|
||||
|
||||
trait HasArguments<'q> {
|
||||
type Arguments;
|
||||
}
|
||||
|
||||
impl<'q> HasArguments<'q> for Sqlite {
|
||||
type Arguments = std::marker::PhantomData<&'q ()>;
|
||||
}
|
||||
|
||||
type SqliteArguments<'q> = <Sqlite as HasArguments<'q>>::Arguments;
|
||||
|
||||
fn foo() {
|
||||
// should not lint
|
||||
// type alias cannot be used as a constructor
|
||||
let _ = <Sqlite as HasArguments>::Arguments::default();
|
||||
|
||||
let _ = SqliteArguments::default();
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// should lint
|
||||
let _ = PhantomData::<usize>::default();
|
||||
|
|
|
@ -13,25 +13,25 @@ LL | inner: PhantomData::default(),
|
|||
| ^^^^^^^^^^^ help: remove this call to `default`
|
||||
|
||||
error: use of `default` to create a unit struct
|
||||
--> $DIR/default_constructed_unit_structs.rs:106:33
|
||||
--> $DIR/default_constructed_unit_structs.rs:128:33
|
||||
|
|
||||
LL | let _ = PhantomData::<usize>::default();
|
||||
| ^^^^^^^^^^^ help: remove this call to `default`
|
||||
|
||||
error: use of `default` to create a unit struct
|
||||
--> $DIR/default_constructed_unit_structs.rs:107:42
|
||||
--> $DIR/default_constructed_unit_structs.rs:129:42
|
||||
|
|
||||
LL | let _: PhantomData<i32> = PhantomData::default();
|
||||
| ^^^^^^^^^^^ help: remove this call to `default`
|
||||
|
||||
error: use of `default` to create a unit struct
|
||||
--> $DIR/default_constructed_unit_structs.rs:108:55
|
||||
--> $DIR/default_constructed_unit_structs.rs:130:55
|
||||
|
|
||||
LL | let _: PhantomData<i32> = std::marker::PhantomData::default();
|
||||
| ^^^^^^^^^^^ help: remove this call to `default`
|
||||
|
||||
error: use of `default` to create a unit struct
|
||||
--> $DIR/default_constructed_unit_structs.rs:109:23
|
||||
--> $DIR/default_constructed_unit_structs.rs:131:23
|
||||
|
|
||||
LL | let _ = UnitStruct::default();
|
||||
| ^^^^^^^^^^^ help: remove this call to `default`
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#![allow(dead_code)]
|
||||
#![warn(clippy::expl_impl_clone_on_copy)]
|
||||
|
||||
|
||||
#[derive(Copy)]
|
||||
struct Qux;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: you are implementing `Clone` explicitly on a `Copy` type
|
||||
--> $DIR/derive.rs:8:1
|
||||
--> $DIR/derive.rs:7:1
|
||||
|
|
||||
LL | / impl Clone for Qux {
|
||||
LL | | fn clone(&self) -> Self {
|
||||
|
@ -9,7 +9,7 @@ LL | | }
|
|||
| |_^
|
||||
|
|
||||
note: consider deriving `Clone` or removing `Copy`
|
||||
--> $DIR/derive.rs:8:1
|
||||
--> $DIR/derive.rs:7:1
|
||||
|
|
||||
LL | / impl Clone for Qux {
|
||||
LL | | fn clone(&self) -> Self {
|
||||
|
@ -20,7 +20,7 @@ LL | | }
|
|||
= note: `-D clippy::expl-impl-clone-on-copy` implied by `-D warnings`
|
||||
|
||||
error: you are implementing `Clone` explicitly on a `Copy` type
|
||||
--> $DIR/derive.rs:32:1
|
||||
--> $DIR/derive.rs:31:1
|
||||
|
|
||||
LL | / impl<'a> Clone for Lt<'a> {
|
||||
LL | | fn clone(&self) -> Self {
|
||||
|
@ -30,7 +30,7 @@ LL | | }
|
|||
| |_^
|
||||
|
|
||||
note: consider deriving `Clone` or removing `Copy`
|
||||
--> $DIR/derive.rs:32:1
|
||||
--> $DIR/derive.rs:31:1
|
||||
|
|
||||
LL | / impl<'a> Clone for Lt<'a> {
|
||||
LL | | fn clone(&self) -> Self {
|
||||
|
@ -40,7 +40,7 @@ LL | | }
|
|||
| |_^
|
||||
|
||||
error: you are implementing `Clone` explicitly on a `Copy` type
|
||||
--> $DIR/derive.rs:43:1
|
||||
--> $DIR/derive.rs:42:1
|
||||
|
|
||||
LL | / impl Clone for BigArray {
|
||||
LL | | fn clone(&self) -> Self {
|
||||
|
@ -50,7 +50,7 @@ LL | | }
|
|||
| |_^
|
||||
|
|
||||
note: consider deriving `Clone` or removing `Copy`
|
||||
--> $DIR/derive.rs:43:1
|
||||
--> $DIR/derive.rs:42:1
|
||||
|
|
||||
LL | / impl Clone for BigArray {
|
||||
LL | | fn clone(&self) -> Self {
|
||||
|
@ -60,7 +60,7 @@ LL | | }
|
|||
| |_^
|
||||
|
||||
error: you are implementing `Clone` explicitly on a `Copy` type
|
||||
--> $DIR/derive.rs:54:1
|
||||
--> $DIR/derive.rs:53:1
|
||||
|
|
||||
LL | / impl Clone for FnPtr {
|
||||
LL | | fn clone(&self) -> Self {
|
||||
|
@ -70,7 +70,7 @@ LL | | }
|
|||
| |_^
|
||||
|
|
||||
note: consider deriving `Clone` or removing `Copy`
|
||||
--> $DIR/derive.rs:54:1
|
||||
--> $DIR/derive.rs:53:1
|
||||
|
|
||||
LL | / impl Clone for FnPtr {
|
||||
LL | | fn clone(&self) -> Self {
|
||||
|
@ -80,7 +80,7 @@ LL | | }
|
|||
| |_^
|
||||
|
||||
error: you are implementing `Clone` explicitly on a `Copy` type
|
||||
--> $DIR/derive.rs:74:1
|
||||
--> $DIR/derive.rs:73:1
|
||||
|
|
||||
LL | / impl<T: Clone> Clone for Generic2<T> {
|
||||
LL | | fn clone(&self) -> Self {
|
||||
|
@ -90,7 +90,7 @@ LL | | }
|
|||
| |_^
|
||||
|
|
||||
note: consider deriving `Clone` or removing `Copy`
|
||||
--> $DIR/derive.rs:74:1
|
||||
--> $DIR/derive.rs:73:1
|
||||
|
|
||||
LL | / impl<T: Clone> Clone for Generic2<T> {
|
||||
LL | | fn clone(&self) -> Self {
|
||||
|
|
|
@ -22,9 +22,9 @@ mod rustc_ok {
|
|||
|
||||
#[expect(illegal_floating_point_literal_pattern)]
|
||||
match x {
|
||||
5.0 => {}
|
||||
6.0 => {}
|
||||
_ => {}
|
||||
5.0 => {},
|
||||
6.0 => {},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,9 +38,9 @@ mod rustc_warn {
|
|||
|
||||
#[expect(illegal_floating_point_literal_pattern)]
|
||||
match x {
|
||||
5 => {}
|
||||
6 => {}
|
||||
_ => {}
|
||||
5 => {},
|
||||
6 => {},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![warn(clippy::ifs_same_cond)]
|
||||
#![allow(clippy::if_same_then_else, clippy::comparison_chain)] // all empty blocks
|
||||
#![allow(clippy::if_same_then_else, clippy::comparison_chain, clippy::needless_else)] // all empty blocks
|
||||
|
||||
fn ifs_same_cond() {
|
||||
let a = 0;
|
||||
|
|
|
@ -18,6 +18,19 @@ pub static DOESNOTLINT2: [u8; 512_001] = {
|
|||
[x; 512_001]
|
||||
};
|
||||
|
||||
fn issue_10741() {
|
||||
#[derive(Copy, Clone)]
|
||||
struct Large([u32; 100_000]);
|
||||
|
||||
fn build() -> Large {
|
||||
Large([0; 100_000])
|
||||
}
|
||||
|
||||
let _x = [build(); 3];
|
||||
|
||||
let _y = [build(), build(), build()];
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let bad = (
|
||||
[0u32; 20_000_000],
|
||||
|
|
|
@ -1,14 +1,30 @@
|
|||
error: allocating a local array larger than 512000 bytes
|
||||
--> $DIR/large_stack_arrays.rs:23:9
|
||||
--> $DIR/large_stack_arrays.rs:29:14
|
||||
|
|
||||
LL | let _x = [build(); 3];
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider allocating on the heap with `vec![build(); 3].into_boxed_slice()`
|
||||
= note: `-D clippy::large-stack-arrays` implied by `-D warnings`
|
||||
|
||||
error: allocating a local array larger than 512000 bytes
|
||||
--> $DIR/large_stack_arrays.rs:31:14
|
||||
|
|
||||
LL | let _y = [build(), build(), build()];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider allocating on the heap with `vec![build(), build(), build()].into_boxed_slice()`
|
||||
|
||||
error: allocating a local array larger than 512000 bytes
|
||||
--> $DIR/large_stack_arrays.rs:36:9
|
||||
|
|
||||
LL | [0u32; 20_000_000],
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider allocating on the heap with `vec![0u32; 20_000_000].into_boxed_slice()`
|
||||
= note: `-D clippy::large-stack-arrays` implied by `-D warnings`
|
||||
|
||||
error: allocating a local array larger than 512000 bytes
|
||||
--> $DIR/large_stack_arrays.rs:24:9
|
||||
--> $DIR/large_stack_arrays.rs:37:9
|
||||
|
|
||||
LL | [S { data: [0; 32] }; 5000],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -16,7 +32,7 @@ LL | [S { data: [0; 32] }; 5000],
|
|||
= help: consider allocating on the heap with `vec![S { data: [0; 32] }; 5000].into_boxed_slice()`
|
||||
|
||||
error: allocating a local array larger than 512000 bytes
|
||||
--> $DIR/large_stack_arrays.rs:25:9
|
||||
--> $DIR/large_stack_arrays.rs:38:9
|
||||
|
|
||||
LL | [Some(""); 20_000_000],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -24,7 +40,7 @@ LL | [Some(""); 20_000_000],
|
|||
= help: consider allocating on the heap with `vec![Some(""); 20_000_000].into_boxed_slice()`
|
||||
|
||||
error: allocating a local array larger than 512000 bytes
|
||||
--> $DIR/large_stack_arrays.rs:26:9
|
||||
--> $DIR/large_stack_arrays.rs:39:9
|
||||
|
|
||||
LL | [E::T(0); 5000],
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
@ -32,12 +48,12 @@ LL | [E::T(0); 5000],
|
|||
= help: consider allocating on the heap with `vec![E::T(0); 5000].into_boxed_slice()`
|
||||
|
||||
error: allocating a local array larger than 512000 bytes
|
||||
--> $DIR/large_stack_arrays.rs:27:9
|
||||
--> $DIR/large_stack_arrays.rs:40:9
|
||||
|
|
||||
LL | [0u8; usize::MAX],
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider allocating on the heap with `vec![0u8; usize::MAX].into_boxed_slice()`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
|
|
|
@ -146,10 +146,20 @@ fn fire() {
|
|||
Variant::A(0, 0)
|
||||
}
|
||||
|
||||
// Should not be renamed
|
||||
let v = if let Variant::A(a, 0) = e() { a } else { return };
|
||||
// Should be renamed
|
||||
let v = if let Variant::B(b) = e() { b } else { return };
|
||||
|
||||
// `mut v` is inserted into the pattern
|
||||
let mut v = if let Variant::B(b) = e() { b } else { return };
|
||||
|
||||
// Nesting works
|
||||
let nested = Ok(Some(e()));
|
||||
let v = if let Ok(Some(Variant::B(b))) | Err(Some(Variant::A(b, _))) = nested {
|
||||
b
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
// dot dot works
|
||||
let v = if let Variant::A(.., a) = e() { a } else { return };
|
||||
}
|
||||
|
||||
fn not_fire() {
|
||||
|
|
|
@ -260,19 +260,42 @@ LL | create_binding_if_some!(w, g());
|
|||
= note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> $DIR/manual_let_else.rs:150:5
|
||||
--> $DIR/manual_let_else.rs:149:5
|
||||
|
|
||||
LL | let v = if let Variant::A(a, 0) = e() { a } else { return };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(a, 0) = e() else { return };`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(v, 0) = e() else { return };`
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> $DIR/manual_let_else.rs:152:5
|
||||
|
|
||||
LL | let v = if let Variant::B(b) = e() { b } else { return };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::B(v) = e() else { return };`
|
||||
LL | let mut v = if let Variant::B(b) = e() { b } else { return };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::B(mut v) = e() else { return };`
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> $DIR/manual_let_else.rs:262:5
|
||||
--> $DIR/manual_let_else.rs:156:5
|
||||
|
|
||||
LL | / let v = if let Ok(Some(Variant::B(b))) | Err(Some(Variant::A(b, _))) = nested {
|
||||
LL | | b
|
||||
LL | | } else {
|
||||
LL | | return;
|
||||
LL | | };
|
||||
| |______^
|
||||
|
|
||||
help: consider writing
|
||||
|
|
||||
LL ~ let (Ok(Some(Variant::B(v))) | Err(Some(Variant::A(v, _)))) = nested else {
|
||||
LL + return;
|
||||
LL + };
|
||||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> $DIR/manual_let_else.rs:162:5
|
||||
|
|
||||
LL | let v = if let Variant::A(.., a) = e() { a } else { return };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(.., v) = e() else { return };`
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> $DIR/manual_let_else.rs:272:5
|
||||
|
|
||||
LL | / let _ = match ff {
|
||||
LL | | Some(value) => value,
|
||||
|
@ -280,5 +303,5 @@ LL | | _ => macro_call!(),
|
|||
LL | | };
|
||||
| |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };`
|
||||
|
||||
error: aborting due to 20 previous errors
|
||||
error: aborting due to 22 previous errors
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ fn fire() {
|
|||
let f = Variant::Bar(1);
|
||||
|
||||
let _value = match f {
|
||||
Variant::Bar(_) | Variant::Baz(_) => (),
|
||||
Variant::Bar(v) | Variant::Baz(v) => v,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
|
|
|
@ -58,10 +58,10 @@ error: this could be rewritten as `let...else`
|
|||
--> $DIR/manual_let_else_match.rs:70:5
|
||||
|
|
||||
LL | / let _value = match f {
|
||||
LL | | Variant::Bar(_) | Variant::Baz(_) => (),
|
||||
LL | | Variant::Bar(v) | Variant::Baz(v) => v,
|
||||
LL | | _ => return,
|
||||
LL | | };
|
||||
| |______^ help: consider writing: `let (Variant::Bar(_) | Variant::Baz(_)) = f else { return };`
|
||||
| |______^ help: consider writing: `let (Variant::Bar(_value) | Variant::Baz(_value)) = f else { return };`
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> $DIR/manual_let_else_match.rs:76:5
|
||||
|
|
|
@ -1,7 +1,20 @@
|
|||
#![feature(exclusive_range_pattern)]
|
||||
#![allow(clippy::match_same_arms)]
|
||||
#![allow(clippy::match_same_arms, dead_code)]
|
||||
#![warn(clippy::match_wild_err_arm)]
|
||||
|
||||
fn issue_10635() {
|
||||
enum Error {
|
||||
A,
|
||||
B,
|
||||
}
|
||||
|
||||
// Don't trigger in const contexts. Const unwrap is not yet stable
|
||||
const X: () = match Ok::<_, Error>(()) {
|
||||
Ok(x) => x,
|
||||
Err(_) => panic!(),
|
||||
};
|
||||
}
|
||||
|
||||
fn match_wild_err_arm() {
|
||||
let x: Result<i32, &str> = Ok(3);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: `Err(_)` matches all errors
|
||||
--> $DIR/match_wild_err_arm.rs:11:9
|
||||
--> $DIR/match_wild_err_arm.rs:24:9
|
||||
|
|
||||
LL | Err(_) => panic!("err"),
|
||||
| ^^^^^^
|
||||
|
@ -8,7 +8,7 @@ LL | Err(_) => panic!("err"),
|
|||
= note: `-D clippy::match-wild-err-arm` implied by `-D warnings`
|
||||
|
||||
error: `Err(_)` matches all errors
|
||||
--> $DIR/match_wild_err_arm.rs:17:9
|
||||
--> $DIR/match_wild_err_arm.rs:30:9
|
||||
|
|
||||
LL | Err(_) => panic!(),
|
||||
| ^^^^^^
|
||||
|
@ -16,7 +16,7 @@ LL | Err(_) => panic!(),
|
|||
= note: match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable
|
||||
|
||||
error: `Err(_)` matches all errors
|
||||
--> $DIR/match_wild_err_arm.rs:23:9
|
||||
--> $DIR/match_wild_err_arm.rs:36:9
|
||||
|
|
||||
LL | Err(_) => {
|
||||
| ^^^^^^
|
||||
|
@ -24,7 +24,7 @@ LL | Err(_) => {
|
|||
= note: match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable
|
||||
|
||||
error: `Err(_e)` matches all errors
|
||||
--> $DIR/match_wild_err_arm.rs:31:9
|
||||
--> $DIR/match_wild_err_arm.rs:44:9
|
||||
|
|
||||
LL | Err(_e) => panic!(),
|
||||
| ^^^^^^^
|
||||
|
|
191
tests/ui/missing_fields_in_debug.rs
Normal file
191
tests/ui/missing_fields_in_debug.rs
Normal file
|
@ -0,0 +1,191 @@
|
|||
#![allow(unused)]
|
||||
#![warn(clippy::missing_fields_in_debug)]
|
||||
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Deref;
|
||||
|
||||
struct NamedStruct1Ignored {
|
||||
data: u8,
|
||||
hidden: u32,
|
||||
}
|
||||
|
||||
impl fmt::Debug for NamedStruct1Ignored {
|
||||
// unused field: hidden
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("NamedStruct1Ignored")
|
||||
.field("data", &self.data)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
struct NamedStructMultipleIgnored {
|
||||
data: u8,
|
||||
hidden: u32,
|
||||
hidden2: String,
|
||||
hidden3: Vec<Vec<i32>>,
|
||||
hidden4: ((((u8), u16), u32), u64),
|
||||
}
|
||||
|
||||
impl fmt::Debug for NamedStructMultipleIgnored {
|
||||
// unused fields: hidden, hidden2, hidden4
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("NamedStructMultipleIgnored")
|
||||
.field("data", &self.data)
|
||||
.field("hidden3", &self.hidden3)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
struct Unit;
|
||||
|
||||
// ok
|
||||
impl fmt::Debug for Unit {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter.debug_struct("Unit").finish()
|
||||
}
|
||||
}
|
||||
|
||||
struct UnnamedStruct1Ignored(String);
|
||||
|
||||
impl fmt::Debug for UnnamedStruct1Ignored {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter.debug_tuple("UnnamedStruct1Ignored").finish()
|
||||
}
|
||||
}
|
||||
|
||||
struct UnnamedStructMultipleIgnored(String, Vec<u8>, i32);
|
||||
|
||||
// tuple structs are not linted
|
||||
impl fmt::Debug for UnnamedStructMultipleIgnored {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_tuple("UnnamedStructMultipleIgnored")
|
||||
.field(&self.1)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
struct NamedStructNonExhaustive {
|
||||
a: u8,
|
||||
b: String,
|
||||
}
|
||||
|
||||
// ok
|
||||
impl fmt::Debug for NamedStructNonExhaustive {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("NamedStructNonExhaustive")
|
||||
.field("a", &self.a)
|
||||
.finish_non_exhaustive() // should not warn here
|
||||
}
|
||||
}
|
||||
|
||||
struct MultiExprDebugImpl {
|
||||
a: u8,
|
||||
b: String,
|
||||
}
|
||||
|
||||
// ok
|
||||
impl fmt::Debug for MultiExprDebugImpl {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut f = formatter.debug_struct("MultiExprDebugImpl");
|
||||
f.field("a", &self.a);
|
||||
f.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DerivedStruct {
|
||||
a: u8,
|
||||
b: i32,
|
||||
}
|
||||
|
||||
// https://github.com/rust-lang/rust-clippy/pull/10616#discussion_r1166846953
|
||||
|
||||
struct Inner {
|
||||
a: usize,
|
||||
b: usize,
|
||||
}
|
||||
|
||||
struct HasInner {
|
||||
inner: Inner,
|
||||
}
|
||||
|
||||
impl HasInner {
|
||||
fn get(&self) -> &Inner {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for HasInner {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let inner = self.get();
|
||||
|
||||
f.debug_struct("HasInner")
|
||||
.field("a", &inner.a)
|
||||
.field("b", &inner.b)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/rust-lang/rust-clippy/pull/10616#discussion_r1170306053
|
||||
struct Foo {
|
||||
a: u8,
|
||||
b: u8,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Foo {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Foo").field("a", &self.a).field("b", &()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/rust-lang/rust-clippy/pull/10616#discussion_r1175473620
|
||||
mod comment1175473620 {
|
||||
use super::*;
|
||||
|
||||
struct Inner {
|
||||
a: usize,
|
||||
b: usize,
|
||||
}
|
||||
struct Wrapper(Inner);
|
||||
|
||||
impl Deref for Wrapper {
|
||||
type Target = Inner;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Wrapper {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Wrapper")
|
||||
.field("a", &self.a)
|
||||
.field("b", &self.b)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/rust-lang/rust-clippy/pull/10616#discussion_r1175488757
|
||||
// PhantomData is an exception and does not need to be included
|
||||
struct WithPD {
|
||||
a: u8,
|
||||
b: u8,
|
||||
c: PhantomData<String>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for WithPD {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("WithPD")
|
||||
.field("a", &self.a)
|
||||
.field("b", &self.b)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
73
tests/ui/missing_fields_in_debug.stderr
Normal file
73
tests/ui/missing_fields_in_debug.stderr
Normal file
|
@ -0,0 +1,73 @@
|
|||
error: manual `Debug` impl does not include all fields
|
||||
--> $DIR/missing_fields_in_debug.rs:13:1
|
||||
|
|
||||
LL | / impl fmt::Debug for NamedStruct1Ignored {
|
||||
LL | | // unused field: hidden
|
||||
LL | | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
LL | | formatter
|
||||
... |
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
note: this field is unused
|
||||
--> $DIR/missing_fields_in_debug.rs:10:5
|
||||
|
|
||||
LL | hidden: u32,
|
||||
| ^^^^^^^^^^^
|
||||
= help: consider including all fields in this `Debug` impl
|
||||
= help: consider calling `.finish_non_exhaustive()` if you intend to ignore fields
|
||||
= note: `-D clippy::missing-fields-in-debug` implied by `-D warnings`
|
||||
|
||||
error: manual `Debug` impl does not include all fields
|
||||
--> $DIR/missing_fields_in_debug.rs:31:1
|
||||
|
|
||||
LL | / impl fmt::Debug for NamedStructMultipleIgnored {
|
||||
LL | | // unused fields: hidden, hidden2, hidden4
|
||||
LL | | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
LL | | formatter
|
||||
... |
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
note: this field is unused
|
||||
--> $DIR/missing_fields_in_debug.rs:25:5
|
||||
|
|
||||
LL | hidden: u32,
|
||||
| ^^^^^^^^^^^
|
||||
note: this field is unused
|
||||
--> $DIR/missing_fields_in_debug.rs:26:5
|
||||
|
|
||||
LL | hidden2: String,
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: this field is unused
|
||||
--> $DIR/missing_fields_in_debug.rs:28:5
|
||||
|
|
||||
LL | hidden4: ((((u8), u16), u32), u64),
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= help: consider including all fields in this `Debug` impl
|
||||
= help: consider calling `.finish_non_exhaustive()` if you intend to ignore fields
|
||||
|
||||
error: manual `Debug` impl does not include all fields
|
||||
--> $DIR/missing_fields_in_debug.rs:92:1
|
||||
|
|
||||
LL | / impl fmt::Debug for MultiExprDebugImpl {
|
||||
LL | | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
LL | | let mut f = formatter.debug_struct("MultiExprDebugImpl");
|
||||
LL | | f.field("a", &self.a);
|
||||
LL | | f.finish()
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
note: this field is unused
|
||||
--> $DIR/missing_fields_in_debug.rs:88:5
|
||||
|
|
||||
LL | b: String,
|
||||
| ^^^^^^^^^
|
||||
= help: consider including all fields in this `Debug` impl
|
||||
= help: consider calling `.finish_non_exhaustive()` if you intend to ignore fields
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
57
tests/ui/needless_else.fixed
Normal file
57
tests/ui/needless_else.fixed
Normal file
|
@ -0,0 +1,57 @@
|
|||
//@run-rustfix
|
||||
#![allow(unused)]
|
||||
#![warn(clippy::needless_else)]
|
||||
#![allow(clippy::suspicious_else_formatting)]
|
||||
|
||||
macro_rules! mac {
|
||||
($test:expr) => {
|
||||
if $test {
|
||||
println!("Test successful!");
|
||||
} else {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! empty_expansion {
|
||||
() => {};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let b = std::hint::black_box(true);
|
||||
|
||||
if b {
|
||||
println!("Foobar");
|
||||
}
|
||||
|
||||
if b {
|
||||
println!("Foobar");
|
||||
} else {
|
||||
// Do not lint because this comment might be important
|
||||
}
|
||||
|
||||
if b {
|
||||
println!("Foobar");
|
||||
} else
|
||||
/* Do not lint because this comment might be important */
|
||||
{
|
||||
}
|
||||
|
||||
// Do not lint because of the expression
|
||||
let _ = if b { 1 } else { 2 };
|
||||
|
||||
// Do not lint because inside a macro
|
||||
mac!(b);
|
||||
|
||||
if b {
|
||||
println!("Foobar");
|
||||
} else {
|
||||
#[cfg(foo)]
|
||||
"Do not lint cfg'd out code"
|
||||
}
|
||||
|
||||
if b {
|
||||
println!("Foobar");
|
||||
} else {
|
||||
empty_expansion!();
|
||||
}
|
||||
}
|
58
tests/ui/needless_else.rs
Normal file
58
tests/ui/needless_else.rs
Normal file
|
@ -0,0 +1,58 @@
|
|||
//@run-rustfix
|
||||
#![allow(unused)]
|
||||
#![warn(clippy::needless_else)]
|
||||
#![allow(clippy::suspicious_else_formatting)]
|
||||
|
||||
macro_rules! mac {
|
||||
($test:expr) => {
|
||||
if $test {
|
||||
println!("Test successful!");
|
||||
} else {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! empty_expansion {
|
||||
() => {};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let b = std::hint::black_box(true);
|
||||
|
||||
if b {
|
||||
println!("Foobar");
|
||||
} else {
|
||||
}
|
||||
|
||||
if b {
|
||||
println!("Foobar");
|
||||
} else {
|
||||
// Do not lint because this comment might be important
|
||||
}
|
||||
|
||||
if b {
|
||||
println!("Foobar");
|
||||
} else
|
||||
/* Do not lint because this comment might be important */
|
||||
{
|
||||
}
|
||||
|
||||
// Do not lint because of the expression
|
||||
let _ = if b { 1 } else { 2 };
|
||||
|
||||
// Do not lint because inside a macro
|
||||
mac!(b);
|
||||
|
||||
if b {
|
||||
println!("Foobar");
|
||||
} else {
|
||||
#[cfg(foo)]
|
||||
"Do not lint cfg'd out code"
|
||||
}
|
||||
|
||||
if b {
|
||||
println!("Foobar");
|
||||
} else {
|
||||
empty_expansion!();
|
||||
}
|
||||
}
|
12
tests/ui/needless_else.stderr
Normal file
12
tests/ui/needless_else.stderr
Normal file
|
@ -0,0 +1,12 @@
|
|||
error: this else branch is empty
|
||||
--> $DIR/needless_else.rs:24:7
|
||||
|
|
||||
LL | } else {
|
||||
| _______^
|
||||
LL | | }
|
||||
| |_____^ help: you can remove it
|
||||
|
|
||||
= note: `-D clippy::needless-else` implied by `-D warnings`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
@ -7,7 +7,8 @@
|
|||
clippy::if_same_then_else,
|
||||
clippy::single_match,
|
||||
clippy::needless_bool,
|
||||
clippy::equatable_if_let
|
||||
clippy::equatable_if_let,
|
||||
clippy::needless_else
|
||||
)]
|
||||
#![warn(clippy::needless_return)]
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
clippy::if_same_then_else,
|
||||
clippy::single_match,
|
||||
clippy::needless_bool,
|
||||
clippy::equatable_if_let
|
||||
clippy::equatable_if_let,
|
||||
clippy::needless_else
|
||||
)]
|
||||
#![warn(clippy::needless_return)]
|
||||
|
||||
|
|
|
@ -1,390 +1,582 @@
|
|||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:27:5
|
||||
--> $DIR/needless_return.rs:28:5
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::needless-return` implied by `-D warnings`
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return true;
|
||||
LL + true
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:31:5
|
||||
--> $DIR/needless_return.rs:32:5
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return true;
|
||||
LL + true
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:36:5
|
||||
--> $DIR/needless_return.rs:37:5
|
||||
|
|
||||
LL | return true;;;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return true;;;
|
||||
LL + true
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:41:5
|
||||
--> $DIR/needless_return.rs:42:5
|
||||
|
|
||||
LL | return true;; ; ;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return true;; ; ;
|
||||
LL + true
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:46:9
|
||||
--> $DIR/needless_return.rs:47:9
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return true;
|
||||
LL + true
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:48:9
|
||||
--> $DIR/needless_return.rs:49:9
|
||||
|
|
||||
LL | return false;
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return false;
|
||||
LL + false
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:54:17
|
||||
--> $DIR/needless_return.rs:55:17
|
||||
|
|
||||
LL | true => return false,
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL | true => false,
|
||||
| ~~~~~
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:56:13
|
||||
--> $DIR/needless_return.rs:57:13
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return true;
|
||||
LL + true
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:63:9
|
||||
--> $DIR/needless_return.rs:64:9
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return true;
|
||||
LL + true
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:65:16
|
||||
--> $DIR/needless_return.rs:66:16
|
||||
|
|
||||
LL | let _ = || return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL | let _ = || true;
|
||||
| ~~~~
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:69:5
|
||||
--> $DIR/needless_return.rs:70:5
|
||||
|
|
||||
LL | return the_answer!();
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return the_answer!();
|
||||
LL + the_answer!()
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:72:21
|
||||
--> $DIR/needless_return.rs:73:21
|
||||
|
|
||||
LL | fn test_void_fun() {
|
||||
| _____________________^
|
||||
LL | | return;
|
||||
| |__________^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - fn test_void_fun() {
|
||||
LL - return;
|
||||
LL + fn test_void_fun() {
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:77:11
|
||||
--> $DIR/needless_return.rs:78:11
|
||||
|
|
||||
LL | if b {
|
||||
| ___________^
|
||||
LL | | return;
|
||||
| |______________^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - if b {
|
||||
LL - return;
|
||||
LL + if b {
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:79:13
|
||||
--> $DIR/needless_return.rs:80:13
|
||||
|
|
||||
LL | } else {
|
||||
| _____________^
|
||||
LL | | return;
|
||||
| |______________^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - } else {
|
||||
LL - return;
|
||||
LL + } else {
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:87:14
|
||||
--> $DIR/needless_return.rs:88:14
|
||||
|
|
||||
LL | _ => return,
|
||||
| ^^^^^^
|
||||
|
|
||||
= help: replace `return` with a unit value
|
||||
help: replace `return` with a unit value
|
||||
|
|
||||
LL | _ => (),
|
||||
| ~~
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:95:24
|
||||
--> $DIR/needless_return.rs:96:24
|
||||
|
|
||||
LL | let _ = 42;
|
||||
| ________________________^
|
||||
LL | | return;
|
||||
| |__________________^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - let _ = 42;
|
||||
LL - return;
|
||||
LL + let _ = 42;
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:98:14
|
||||
--> $DIR/needless_return.rs:99:14
|
||||
|
|
||||
LL | _ => return,
|
||||
| ^^^^^^
|
||||
|
|
||||
= help: replace `return` with a unit value
|
||||
help: replace `return` with a unit value
|
||||
|
|
||||
LL | _ => (),
|
||||
| ~~
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:111:9
|
||||
--> $DIR/needless_return.rs:112:9
|
||||
|
|
||||
LL | return String::from("test");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return String::from("test");
|
||||
LL + String::from("test")
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:113:9
|
||||
--> $DIR/needless_return.rs:114:9
|
||||
|
|
||||
LL | return String::new();
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return String::new();
|
||||
LL + String::new()
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:135:32
|
||||
--> $DIR/needless_return.rs:136:32
|
||||
|
|
||||
LL | bar.unwrap_or_else(|_| return)
|
||||
| ^^^^^^
|
||||
|
|
||||
= help: replace `return` with an empty block
|
||||
help: replace `return` with an empty block
|
||||
|
|
||||
LL | bar.unwrap_or_else(|_| {})
|
||||
| ~~
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:139:21
|
||||
--> $DIR/needless_return.rs:140:21
|
||||
|
|
||||
LL | let _ = || {
|
||||
| _____________________^
|
||||
LL | | return;
|
||||
| |__________________^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - let _ = || {
|
||||
LL - return;
|
||||
LL + let _ = || {
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:142:20
|
||||
--> $DIR/needless_return.rs:143:20
|
||||
|
|
||||
LL | let _ = || return;
|
||||
| ^^^^^^
|
||||
|
|
||||
= help: replace `return` with an empty block
|
||||
help: replace `return` with an empty block
|
||||
|
|
||||
LL | let _ = || {};
|
||||
| ~~
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:148:32
|
||||
--> $DIR/needless_return.rs:149:32
|
||||
|
|
||||
LL | res.unwrap_or_else(|_| return Foo)
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL | res.unwrap_or_else(|_| Foo)
|
||||
| ~~~
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:157:5
|
||||
--> $DIR/needless_return.rs:158:5
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return true;
|
||||
LL + true
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:161:5
|
||||
--> $DIR/needless_return.rs:162:5
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return true;
|
||||
LL + true
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:166:9
|
||||
--> $DIR/needless_return.rs:167:9
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return true;
|
||||
LL + true
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:168:9
|
||||
--> $DIR/needless_return.rs:169:9
|
||||
|
|
||||
LL | return false;
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return false;
|
||||
LL + false
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:174:17
|
||||
--> $DIR/needless_return.rs:175:17
|
||||
|
|
||||
LL | true => return false,
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL | true => false,
|
||||
| ~~~~~
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:176:13
|
||||
--> $DIR/needless_return.rs:177:13
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return true;
|
||||
LL + true
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:183:9
|
||||
--> $DIR/needless_return.rs:184:9
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return true;
|
||||
LL + true
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:185:16
|
||||
--> $DIR/needless_return.rs:186:16
|
||||
|
|
||||
LL | let _ = || return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL | let _ = || true;
|
||||
| ~~~~
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:189:5
|
||||
--> $DIR/needless_return.rs:190:5
|
||||
|
|
||||
LL | return the_answer!();
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return the_answer!();
|
||||
LL + the_answer!()
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:192:33
|
||||
--> $DIR/needless_return.rs:193:33
|
||||
|
|
||||
LL | async fn async_test_void_fun() {
|
||||
| _________________________________^
|
||||
LL | | return;
|
||||
| |__________^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - async fn async_test_void_fun() {
|
||||
LL - return;
|
||||
LL + async fn async_test_void_fun() {
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:197:11
|
||||
--> $DIR/needless_return.rs:198:11
|
||||
|
|
||||
LL | if b {
|
||||
| ___________^
|
||||
LL | | return;
|
||||
| |______________^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - if b {
|
||||
LL - return;
|
||||
LL + if b {
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:199:13
|
||||
--> $DIR/needless_return.rs:200:13
|
||||
|
|
||||
LL | } else {
|
||||
| _____________^
|
||||
LL | | return;
|
||||
| |______________^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - } else {
|
||||
LL - return;
|
||||
LL + } else {
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:207:14
|
||||
--> $DIR/needless_return.rs:208:14
|
||||
|
|
||||
LL | _ => return,
|
||||
| ^^^^^^
|
||||
|
|
||||
= help: replace `return` with a unit value
|
||||
help: replace `return` with a unit value
|
||||
|
|
||||
LL | _ => (),
|
||||
| ~~
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:220:9
|
||||
--> $DIR/needless_return.rs:221:9
|
||||
|
|
||||
LL | return String::from("test");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return String::from("test");
|
||||
LL + String::from("test")
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:222:9
|
||||
--> $DIR/needless_return.rs:223:9
|
||||
|
|
||||
LL | return String::new();
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return String::new();
|
||||
LL + String::new()
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:238:5
|
||||
--> $DIR/needless_return.rs:239:5
|
||||
|
|
||||
LL | return format!("Hello {}", "world!");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return format!("Hello {}", "world!");
|
||||
LL + format!("Hello {}", "world!")
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:250:9
|
||||
--> $DIR/needless_return.rs:251:9
|
||||
|
|
||||
LL | return true;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL ~ true
|
||||
LL | } else {
|
||||
LL | return false;
|
||||
LL ~ }
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:252:9
|
||||
--> $DIR/needless_return.rs:253:9
|
||||
|
|
||||
LL | return false;
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL ~ false
|
||||
LL ~ }
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:259:13
|
||||
--> $DIR/needless_return.rs:260:13
|
||||
|
|
||||
LL | return 10;
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL ~ 10
|
||||
LL | },
|
||||
...
|
||||
LL | },
|
||||
LL ~ }
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:262:13
|
||||
--> $DIR/needless_return.rs:263:13
|
||||
|
|
||||
LL | return 100;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL ~ 100
|
||||
LL | },
|
||||
LL ~ }
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:270:9
|
||||
--> $DIR/needless_return.rs:271:9
|
||||
|
|
||||
LL | return 0;
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL ~ 0
|
||||
LL ~ }
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:277:13
|
||||
--> $DIR/needless_return.rs:278:13
|
||||
|
|
||||
LL | return *(x as *const isize);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL ~ *(x as *const isize)
|
||||
LL | } else {
|
||||
LL | return !*(x as *const isize);
|
||||
LL ~ }
|
||||
LL ~ }
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:279:13
|
||||
--> $DIR/needless_return.rs:280:13
|
||||
|
|
||||
LL | return !*(x as *const isize);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL ~ !*(x as *const isize)
|
||||
LL ~ }
|
||||
LL ~ }
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:286:20
|
||||
--> $DIR/needless_return.rs:287:20
|
||||
|
|
||||
LL | let _ = 42;
|
||||
| ____________________^
|
||||
|
@ -392,47 +584,73 @@ LL | |
|
|||
LL | | return;
|
||||
| |______________^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - let _ = 42;
|
||||
LL -
|
||||
LL - return;
|
||||
LL + let _ = 42;
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:293:20
|
||||
--> $DIR/needless_return.rs:294:20
|
||||
|
|
||||
LL | let _ = 42; return;
|
||||
| ^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - let _ = 42; return;
|
||||
LL + let _ = 42;
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:305:9
|
||||
--> $DIR/needless_return.rs:306:9
|
||||
|
|
||||
LL | return Ok(format!("ok!"));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return Ok(format!("ok!"));
|
||||
LL + Ok(format!("ok!"))
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:307:9
|
||||
--> $DIR/needless_return.rs:308:9
|
||||
|
|
||||
LL | return Err(format!("err!"));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return Err(format!("err!"));
|
||||
LL + Err(format!("err!"))
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:313:9
|
||||
--> $DIR/needless_return.rs:314:9
|
||||
|
|
||||
LL | return if true { 1 } else { 2 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
help: remove `return`
|
||||
|
|
||||
LL - return if true { 1 } else { 2 };
|
||||
LL + if true { 1 } else { 2 }
|
||||
|
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:317:9
|
||||
--> $DIR/needless_return.rs:318:9
|
||||
|
|
||||
LL | return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return` and wrap the sequence with parentheses
|
||||
help: remove `return` and wrap the sequence with parentheses
|
||||
|
|
||||
LL - return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 };
|
||||
LL + (if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 })
|
||||
|
|
||||
|
||||
error: aborting due to 52 previous errors
|
||||
|
||||
|
|
|
@ -110,3 +110,17 @@ fn issue_10435() {
|
|||
println!("{}", line!());
|
||||
}
|
||||
}
|
||||
|
||||
fn issue10836() {
|
||||
struct Foo(bool);
|
||||
impl std::ops::Not for Foo {
|
||||
type Output = bool;
|
||||
|
||||
fn not(self) -> Self::Output {
|
||||
!self.0
|
||||
}
|
||||
}
|
||||
|
||||
// Should not lint
|
||||
let _: bool = !!Foo(true);
|
||||
}
|
||||
|
|
55
tests/ui/ptr_cast_constness.fixed
Normal file
55
tests/ui/ptr_cast_constness.fixed
Normal file
|
@ -0,0 +1,55 @@
|
|||
//@run-rustfix
|
||||
//@aux-build:proc_macros.rs
|
||||
|
||||
#![warn(clippy::ptr_cast_constness)]
|
||||
|
||||
extern crate proc_macros;
|
||||
use proc_macros::{external, inline_macros};
|
||||
|
||||
#[inline_macros]
|
||||
fn main() {
|
||||
let ptr: *const u32 = &42_u32;
|
||||
let mut_ptr: *mut u32 = &mut 42_u32;
|
||||
|
||||
let _ = ptr as *const i32;
|
||||
let _ = mut_ptr as *mut i32;
|
||||
|
||||
// Make sure the lint can handle the difference in their operator precedences.
|
||||
unsafe {
|
||||
let ptr_ptr: *const *const u32 = &ptr;
|
||||
let _ = (*ptr_ptr).cast_mut();
|
||||
}
|
||||
|
||||
let _ = ptr.cast_mut();
|
||||
let _ = mut_ptr.cast_const();
|
||||
|
||||
// Lint this, since pointer::cast_mut and pointer::cast_const have ?Sized
|
||||
let ptr_of_array: *const [u32; 4] = &[1, 2, 3, 4];
|
||||
let _ = ptr_of_array as *const [u32];
|
||||
let _ = ptr_of_array as *const dyn std::fmt::Debug;
|
||||
|
||||
// Make sure the lint is triggered inside a macro
|
||||
let _ = inline!($ptr as *const i32);
|
||||
|
||||
// Do not lint inside macros from external crates
|
||||
let _ = external!($ptr as *const i32);
|
||||
}
|
||||
|
||||
#[clippy::msrv = "1.64"]
|
||||
fn _msrv_1_64() {
|
||||
let ptr: *const u32 = &42_u32;
|
||||
let mut_ptr: *mut u32 = &mut 42_u32;
|
||||
|
||||
// `pointer::cast_const` and `pointer::cast_mut` were stabilized in 1.65. Do not lint this
|
||||
let _ = ptr as *mut i32;
|
||||
let _ = mut_ptr as *const i32;
|
||||
}
|
||||
|
||||
#[clippy::msrv = "1.65"]
|
||||
fn _msrv_1_65() {
|
||||
let ptr: *const u32 = &42_u32;
|
||||
let mut_ptr: *mut u32 = &mut 42_u32;
|
||||
|
||||
let _ = ptr.cast_mut();
|
||||
let _ = mut_ptr.cast_const();
|
||||
}
|
55
tests/ui/ptr_cast_constness.rs
Normal file
55
tests/ui/ptr_cast_constness.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
//@run-rustfix
|
||||
//@aux-build:proc_macros.rs
|
||||
|
||||
#![warn(clippy::ptr_cast_constness)]
|
||||
|
||||
extern crate proc_macros;
|
||||
use proc_macros::{external, inline_macros};
|
||||
|
||||
#[inline_macros]
|
||||
fn main() {
|
||||
let ptr: *const u32 = &42_u32;
|
||||
let mut_ptr: *mut u32 = &mut 42_u32;
|
||||
|
||||
let _ = ptr as *const i32;
|
||||
let _ = mut_ptr as *mut i32;
|
||||
|
||||
// Make sure the lint can handle the difference in their operator precedences.
|
||||
unsafe {
|
||||
let ptr_ptr: *const *const u32 = &ptr;
|
||||
let _ = *ptr_ptr as *mut i32;
|
||||
}
|
||||
|
||||
let _ = ptr as *mut i32;
|
||||
let _ = mut_ptr as *const i32;
|
||||
|
||||
// Lint this, since pointer::cast_mut and pointer::cast_const have ?Sized
|
||||
let ptr_of_array: *const [u32; 4] = &[1, 2, 3, 4];
|
||||
let _ = ptr_of_array as *const [u32];
|
||||
let _ = ptr_of_array as *const dyn std::fmt::Debug;
|
||||
|
||||
// Make sure the lint is triggered inside a macro
|
||||
let _ = inline!($ptr as *const i32);
|
||||
|
||||
// Do not lint inside macros from external crates
|
||||
let _ = external!($ptr as *const i32);
|
||||
}
|
||||
|
||||
#[clippy::msrv = "1.64"]
|
||||
fn _msrv_1_64() {
|
||||
let ptr: *const u32 = &42_u32;
|
||||
let mut_ptr: *mut u32 = &mut 42_u32;
|
||||
|
||||
// `pointer::cast_const` and `pointer::cast_mut` were stabilized in 1.65. Do not lint this
|
||||
let _ = ptr as *mut i32;
|
||||
let _ = mut_ptr as *const i32;
|
||||
}
|
||||
|
||||
#[clippy::msrv = "1.65"]
|
||||
fn _msrv_1_65() {
|
||||
let ptr: *const u32 = &42_u32;
|
||||
let mut_ptr: *mut u32 = &mut 42_u32;
|
||||
|
||||
let _ = ptr as *mut i32;
|
||||
let _ = mut_ptr as *const i32;
|
||||
}
|
34
tests/ui/ptr_cast_constness.stderr
Normal file
34
tests/ui/ptr_cast_constness.stderr
Normal file
|
@ -0,0 +1,34 @@
|
|||
error: `as` casting between raw pointers while changing its constness
|
||||
--> $DIR/ptr_cast_constness.rs:20:17
|
||||
|
|
||||
LL | let _ = *ptr_ptr as *mut i32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `(*ptr_ptr).cast_mut()`
|
||||
|
|
||||
= note: `-D clippy::ptr-cast-constness` implied by `-D warnings`
|
||||
|
||||
error: `as` casting between raw pointers while changing its constness
|
||||
--> $DIR/ptr_cast_constness.rs:23:13
|
||||
|
|
||||
LL | let _ = ptr as *mut i32;
|
||||
| ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()`
|
||||
|
||||
error: `as` casting between raw pointers while changing its constness
|
||||
--> $DIR/ptr_cast_constness.rs:24:13
|
||||
|
|
||||
LL | let _ = mut_ptr as *const i32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()`
|
||||
|
||||
error: `as` casting between raw pointers while changing its constness
|
||||
--> $DIR/ptr_cast_constness.rs:53:13
|
||||
|
|
||||
LL | let _ = ptr as *mut i32;
|
||||
| ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()`
|
||||
|
||||
error: `as` casting between raw pointers while changing its constness
|
||||
--> $DIR/ptr_cast_constness.rs:54:13
|
||||
|
|
||||
LL | let _ = mut_ptr as *const i32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// Issue #5746
|
||||
#![warn(clippy::redundant_pattern_matching)]
|
||||
#![allow(clippy::if_same_then_else, clippy::equatable_if_let)]
|
||||
#![allow(clippy::if_same_then_else, clippy::equatable_if_let, clippy::needless_else)]
|
||||
use std::task::Poll::{Pending, Ready};
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// Issue #5746
|
||||
#![warn(clippy::redundant_pattern_matching)]
|
||||
#![allow(clippy::if_same_then_else, clippy::equatable_if_let)]
|
||||
#![allow(clippy::if_same_then_else, clippy::equatable_if_let, clippy::needless_else)]
|
||||
use std::task::Poll::{Pending, Ready};
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -47,6 +47,7 @@ fn main() {
|
|||
|
||||
issue6067();
|
||||
issue10726();
|
||||
issue10803();
|
||||
|
||||
let _ = if gen_opt().is_some() {
|
||||
1
|
||||
|
@ -107,3 +108,14 @@ fn issue10726() {
|
|||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
fn issue10803() {
|
||||
let x = Some(42);
|
||||
|
||||
let _ = x.is_some();
|
||||
|
||||
let _ = x.is_none();
|
||||
|
||||
// Don't lint
|
||||
let _ = matches!(x, Some(16));
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ fn main() {
|
|||
|
||||
issue6067();
|
||||
issue10726();
|
||||
issue10803();
|
||||
|
||||
let _ = if let Some(_) = gen_opt() {
|
||||
1
|
||||
|
@ -134,3 +135,14 @@ fn issue10726() {
|
|||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
fn issue10803() {
|
||||
let x = Some(42);
|
||||
|
||||
let _ = matches!(x, Some(_));
|
||||
|
||||
let _ = matches!(x, None);
|
||||
|
||||
// Don't lint
|
||||
let _ = matches!(x, Some(16));
|
||||
}
|
||||
|
|
|
@ -77,49 +77,49 @@ LL | let _ = if let Some(_) = opt { true } else { false };
|
|||
| -------^^^^^^^------ help: try this: `if opt.is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:60:20
|
||||
--> $DIR/redundant_pattern_matching_option.rs:61:20
|
||||
|
|
||||
LL | let _ = if let Some(_) = gen_opt() {
|
||||
| -------^^^^^^^------------ help: try this: `if gen_opt().is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_none()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:62:19
|
||||
--> $DIR/redundant_pattern_matching_option.rs:63:19
|
||||
|
|
||||
LL | } else if let None = gen_opt() {
|
||||
| -------^^^^------------ help: try this: `if gen_opt().is_none()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:68:12
|
||||
--> $DIR/redundant_pattern_matching_option.rs:69:12
|
||||
|
|
||||
LL | if let Some(..) = gen_opt() {}
|
||||
| -------^^^^^^^^------------ help: try this: `if gen_opt().is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:83:12
|
||||
--> $DIR/redundant_pattern_matching_option.rs:84:12
|
||||
|
|
||||
LL | if let Some(_) = Some(42) {}
|
||||
| -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_none()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:85:12
|
||||
--> $DIR/redundant_pattern_matching_option.rs:86:12
|
||||
|
|
||||
LL | if let None = None::<()> {}
|
||||
| -------^^^^------------- help: try this: `if None::<()>.is_none()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:87:15
|
||||
--> $DIR/redundant_pattern_matching_option.rs:88:15
|
||||
|
|
||||
LL | while let Some(_) = Some(42) {}
|
||||
| ----------^^^^^^^----------- help: try this: `while Some(42).is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_none()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:89:15
|
||||
--> $DIR/redundant_pattern_matching_option.rs:90:15
|
||||
|
|
||||
LL | while let None = None::<()> {}
|
||||
| ----------^^^^------------- help: try this: `while None::<()>.is_none()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:91:5
|
||||
--> $DIR/redundant_pattern_matching_option.rs:92:5
|
||||
|
|
||||
LL | / match Some(42) {
|
||||
LL | | Some(_) => true,
|
||||
|
@ -128,7 +128,7 @@ LL | | };
|
|||
| |_____^ help: try this: `Some(42).is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_none()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:96:5
|
||||
--> $DIR/redundant_pattern_matching_option.rs:97:5
|
||||
|
|
||||
LL | / match None::<()> {
|
||||
LL | | Some(_) => false,
|
||||
|
@ -137,19 +137,19 @@ LL | | };
|
|||
| |_____^ help: try this: `None::<()>.is_none()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_none()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:104:12
|
||||
--> $DIR/redundant_pattern_matching_option.rs:105:12
|
||||
|
|
||||
LL | if let None = *(&None::<()>) {}
|
||||
| -------^^^^----------------- help: try this: `if (&None::<()>).is_none()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_none()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:105:12
|
||||
--> $DIR/redundant_pattern_matching_option.rs:106:12
|
||||
|
|
||||
LL | if let None = *&None::<()> {}
|
||||
| -------^^^^--------------- help: try this: `if (&None::<()>).is_none()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:111:5
|
||||
--> $DIR/redundant_pattern_matching_option.rs:112:5
|
||||
|
|
||||
LL | / match x {
|
||||
LL | | Some(_) => true,
|
||||
|
@ -158,7 +158,7 @@ LL | | };
|
|||
| |_____^ help: try this: `x.is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_none()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:116:5
|
||||
--> $DIR/redundant_pattern_matching_option.rs:117:5
|
||||
|
|
||||
LL | / match x {
|
||||
LL | | None => true,
|
||||
|
@ -167,7 +167,7 @@ LL | | };
|
|||
| |_____^ help: try this: `x.is_none()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_none()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:121:5
|
||||
--> $DIR/redundant_pattern_matching_option.rs:122:5
|
||||
|
|
||||
LL | / match x {
|
||||
LL | | Some(_) => false,
|
||||
|
@ -176,7 +176,7 @@ LL | | };
|
|||
| |_____^ help: try this: `x.is_none()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:126:5
|
||||
--> $DIR/redundant_pattern_matching_option.rs:127:5
|
||||
|
|
||||
LL | / match x {
|
||||
LL | | None => false,
|
||||
|
@ -184,5 +184,17 @@ LL | | _ => true,
|
|||
LL | | };
|
||||
| |_____^ help: try this: `x.is_some()`
|
||||
|
||||
error: aborting due to 26 previous errors
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:142:13
|
||||
|
|
||||
LL | let _ = matches!(x, Some(_));
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: try this: `x.is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_none()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:144:13
|
||||
|
|
||||
LL | let _ = matches!(x, None);
|
||||
| ^^^^^^^^^^^^^^^^^ help: try this: `x.is_none()`
|
||||
|
||||
error: aborting due to 28 previous errors
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ fn main() {
|
|||
issue6067();
|
||||
issue6065();
|
||||
issue10726();
|
||||
issue10803();
|
||||
|
||||
let _ = if gen_res().is_ok() {
|
||||
1
|
||||
|
@ -133,3 +134,17 @@ fn issue10726() {
|
|||
_ => true,
|
||||
};
|
||||
}
|
||||
|
||||
fn issue10803() {
|
||||
let x: Result<i32, i32> = Ok(42);
|
||||
|
||||
let _ = x.is_ok();
|
||||
|
||||
let _ = x.is_err();
|
||||
|
||||
// Don't lint
|
||||
let _ = matches!(x, Ok(16));
|
||||
|
||||
// Don't lint
|
||||
let _ = matches!(x, Err(16));
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ fn main() {
|
|||
issue6067();
|
||||
issue6065();
|
||||
issue10726();
|
||||
issue10803();
|
||||
|
||||
let _ = if let Ok(_) = gen_res() {
|
||||
1
|
||||
|
@ -163,3 +164,17 @@ fn issue10726() {
|
|||
_ => true,
|
||||
};
|
||||
}
|
||||
|
||||
fn issue10803() {
|
||||
let x: Result<i32, i32> = Ok(42);
|
||||
|
||||
let _ = matches!(x, Ok(_));
|
||||
|
||||
let _ = matches!(x, Err(_));
|
||||
|
||||
// Don't lint
|
||||
let _ = matches!(x, Ok(16));
|
||||
|
||||
// Don't lint
|
||||
let _ = matches!(x, Err(16));
|
||||
}
|
||||
|
|
|
@ -73,67 +73,67 @@ LL | let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false };
|
|||
| -------^^^^^--------------------- help: try this: `if Ok::<usize, ()>(4).is_ok()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ok()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:60:20
|
||||
--> $DIR/redundant_pattern_matching_result.rs:61:20
|
||||
|
|
||||
LL | let _ = if let Ok(_) = gen_res() {
|
||||
| -------^^^^^------------ help: try this: `if gen_res().is_ok()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_err()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:62:19
|
||||
--> $DIR/redundant_pattern_matching_result.rs:63:19
|
||||
|
|
||||
LL | } else if let Err(_) = gen_res() {
|
||||
| -------^^^^^^------------ help: try this: `if gen_res().is_err()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:85:19
|
||||
--> $DIR/redundant_pattern_matching_result.rs:86:19
|
||||
|
|
||||
LL | while let Some(_) = r#try!(result_opt()) {}
|
||||
| ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:86:16
|
||||
--> $DIR/redundant_pattern_matching_result.rs:87:16
|
||||
|
|
||||
LL | if let Some(_) = r#try!(result_opt()) {}
|
||||
| -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:92:12
|
||||
--> $DIR/redundant_pattern_matching_result.rs:93:12
|
||||
|
|
||||
LL | if let Some(_) = m!() {}
|
||||
| -------^^^^^^^------- help: try this: `if m!().is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:93:15
|
||||
--> $DIR/redundant_pattern_matching_result.rs:94:15
|
||||
|
|
||||
LL | while let Some(_) = m!() {}
|
||||
| ----------^^^^^^^------- help: try this: `while m!().is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ok()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:111:12
|
||||
--> $DIR/redundant_pattern_matching_result.rs:112:12
|
||||
|
|
||||
LL | if let Ok(_) = Ok::<i32, i32>(42) {}
|
||||
| -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_err()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:113:12
|
||||
--> $DIR/redundant_pattern_matching_result.rs:114:12
|
||||
|
|
||||
LL | if let Err(_) = Err::<i32, i32>(42) {}
|
||||
| -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ok()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:115:15
|
||||
--> $DIR/redundant_pattern_matching_result.rs:116:15
|
||||
|
|
||||
LL | while let Ok(_) = Ok::<i32, i32>(10) {}
|
||||
| ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_err()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:117:15
|
||||
--> $DIR/redundant_pattern_matching_result.rs:118:15
|
||||
|
|
||||
LL | while let Err(_) = Ok::<i32, i32>(10) {}
|
||||
| ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ok()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:119:5
|
||||
--> $DIR/redundant_pattern_matching_result.rs:120:5
|
||||
|
|
||||
LL | / match Ok::<i32, i32>(42) {
|
||||
LL | | Ok(_) => true,
|
||||
|
@ -142,7 +142,7 @@ LL | | };
|
|||
| |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_err()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:124:5
|
||||
--> $DIR/redundant_pattern_matching_result.rs:125:5
|
||||
|
|
||||
LL | / match Err::<i32, i32>(42) {
|
||||
LL | | Ok(_) => false,
|
||||
|
@ -151,7 +151,7 @@ LL | | };
|
|||
| |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ok()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:134:5
|
||||
--> $DIR/redundant_pattern_matching_result.rs:135:5
|
||||
|
|
||||
LL | / match x {
|
||||
LL | | Ok(_) => true,
|
||||
|
@ -160,7 +160,7 @@ LL | | };
|
|||
| |_____^ help: try this: `x.is_ok()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_err()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:139:5
|
||||
--> $DIR/redundant_pattern_matching_result.rs:140:5
|
||||
|
|
||||
LL | / match x {
|
||||
LL | | Ok(_) => false,
|
||||
|
@ -169,7 +169,7 @@ LL | | };
|
|||
| |_____^ help: try this: `x.is_err()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_err()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:144:5
|
||||
--> $DIR/redundant_pattern_matching_result.rs:145:5
|
||||
|
|
||||
LL | / match x {
|
||||
LL | | Err(_) => true,
|
||||
|
@ -178,7 +178,7 @@ LL | | };
|
|||
| |_____^ help: try this: `x.is_err()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ok()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:149:5
|
||||
--> $DIR/redundant_pattern_matching_result.rs:150:5
|
||||
|
|
||||
LL | / match x {
|
||||
LL | | Err(_) => false,
|
||||
|
@ -186,5 +186,17 @@ LL | | _ => true,
|
|||
LL | | };
|
||||
| |_____^ help: try this: `x.is_ok()`
|
||||
|
||||
error: aborting due to 26 previous errors
|
||||
error: redundant pattern matching, consider using `is_ok()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:171:13
|
||||
|
|
||||
LL | let _ = matches!(x, Ok(_));
|
||||
| ^^^^^^^^^^^^^^^^^^ help: try this: `x.is_ok()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_err()`
|
||||
--> $DIR/redundant_pattern_matching_result.rs:173:13
|
||||
|
|
||||
LL | let _ = matches!(x, Err(_));
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: try this: `x.is_err()`
|
||||
|
||||
error: aborting due to 28 previous errors
|
||||
|
||||
|
|
|
@ -42,6 +42,11 @@ fn syntax_error() {
|
|||
let escaped_string_span = Regex::new("\\b\\c");
|
||||
|
||||
let aux_span = Regex::new("(?ixi)");
|
||||
|
||||
let should_not_lint = Regex::new("(?u).");
|
||||
let should_not_lint = BRegex::new("(?u).");
|
||||
let invalid_utf8_should_not_lint = BRegex::new("(?-u).");
|
||||
let invalid_utf8_should_lint = Regex::new("(?-u).");
|
||||
}
|
||||
|
||||
fn trivial_regex() {
|
||||
|
@ -71,6 +76,8 @@ fn trivial_regex() {
|
|||
// non-trivial regexes
|
||||
let non_trivial_dot = Regex::new("a.b");
|
||||
let non_trivial_dot_builder = RegexBuilder::new("a.b");
|
||||
let non_trivial_dot = Regex::new(".");
|
||||
let non_trivial_dot = BRegex::new(".");
|
||||
let non_trivial_eq = Regex::new("^foo|bar$");
|
||||
let non_trivial_starts_with = Regex::new("^foo|bar");
|
||||
let non_trivial_ends_with = Regex::new("^foo|bar");
|
||||
|
|
|
@ -99,8 +99,14 @@ error: regex syntax error: duplicate flag
|
|||
LL | let aux_span = Regex::new("(?ixi)");
|
||||
| ^ ^
|
||||
|
||||
error: regex syntax error: pattern can match invalid UTF-8
|
||||
--> $DIR/regex.rs:49:53
|
||||
|
|
||||
LL | let invalid_utf8_should_lint = Regex::new("(?-u).");
|
||||
| ^
|
||||
|
||||
error: trivial regex
|
||||
--> $DIR/regex.rs:48:33
|
||||
--> $DIR/regex.rs:53:33
|
||||
|
|
||||
LL | let trivial_eq = Regex::new("^foobar$");
|
||||
| ^^^^^^^^^^
|
||||
|
@ -108,7 +114,7 @@ LL | let trivial_eq = Regex::new("^foobar$");
|
|||
= help: consider using `==` on `str`s
|
||||
|
||||
error: trivial regex
|
||||
--> $DIR/regex.rs:50:48
|
||||
--> $DIR/regex.rs:55:48
|
||||
|
|
||||
LL | let trivial_eq_builder = RegexBuilder::new("^foobar$");
|
||||
| ^^^^^^^^^^
|
||||
|
@ -116,7 +122,7 @@ LL | let trivial_eq_builder = RegexBuilder::new("^foobar$");
|
|||
= help: consider using `==` on `str`s
|
||||
|
||||
error: trivial regex
|
||||
--> $DIR/regex.rs:52:42
|
||||
--> $DIR/regex.rs:57:42
|
||||
|
|
||||
LL | let trivial_starts_with = Regex::new("^foobar");
|
||||
| ^^^^^^^^^
|
||||
|
@ -124,7 +130,7 @@ LL | let trivial_starts_with = Regex::new("^foobar");
|
|||
= help: consider using `str::starts_with`
|
||||
|
||||
error: trivial regex
|
||||
--> $DIR/regex.rs:54:40
|
||||
--> $DIR/regex.rs:59:40
|
||||
|
|
||||
LL | let trivial_ends_with = Regex::new("foobar$");
|
||||
| ^^^^^^^^^
|
||||
|
@ -132,7 +138,7 @@ LL | let trivial_ends_with = Regex::new("foobar$");
|
|||
= help: consider using `str::ends_with`
|
||||
|
||||
error: trivial regex
|
||||
--> $DIR/regex.rs:56:39
|
||||
--> $DIR/regex.rs:61:39
|
||||
|
|
||||
LL | let trivial_contains = Regex::new("foobar");
|
||||
| ^^^^^^^^
|
||||
|
@ -140,7 +146,7 @@ LL | let trivial_contains = Regex::new("foobar");
|
|||
= help: consider using `str::contains`
|
||||
|
||||
error: trivial regex
|
||||
--> $DIR/regex.rs:58:39
|
||||
--> $DIR/regex.rs:63:39
|
||||
|
|
||||
LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX);
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
@ -148,7 +154,7 @@ LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX);
|
|||
= help: consider using `str::contains`
|
||||
|
||||
error: trivial regex
|
||||
--> $DIR/regex.rs:60:40
|
||||
--> $DIR/regex.rs:65:40
|
||||
|
|
||||
LL | let trivial_backslash = Regex::new("a/.b");
|
||||
| ^^^^^^^
|
||||
|
@ -156,7 +162,7 @@ LL | let trivial_backslash = Regex::new("a/.b");
|
|||
= help: consider using `str::contains`
|
||||
|
||||
error: trivial regex
|
||||
--> $DIR/regex.rs:63:36
|
||||
--> $DIR/regex.rs:68:36
|
||||
|
|
||||
LL | let trivial_empty = Regex::new("");
|
||||
| ^^
|
||||
|
@ -164,7 +170,7 @@ LL | let trivial_empty = Regex::new("");
|
|||
= help: the regex is unlikely to be useful as it is
|
||||
|
||||
error: trivial regex
|
||||
--> $DIR/regex.rs:65:36
|
||||
--> $DIR/regex.rs:70:36
|
||||
|
|
||||
LL | let trivial_empty = Regex::new("^");
|
||||
| ^^^
|
||||
|
@ -172,7 +178,7 @@ LL | let trivial_empty = Regex::new("^");
|
|||
= help: the regex is unlikely to be useful as it is
|
||||
|
||||
error: trivial regex
|
||||
--> $DIR/regex.rs:67:36
|
||||
--> $DIR/regex.rs:72:36
|
||||
|
|
||||
LL | let trivial_empty = Regex::new("^$");
|
||||
| ^^^^
|
||||
|
@ -180,12 +186,12 @@ LL | let trivial_empty = Regex::new("^$");
|
|||
= help: consider using `str::is_empty`
|
||||
|
||||
error: trivial regex
|
||||
--> $DIR/regex.rs:69:44
|
||||
--> $DIR/regex.rs:74:44
|
||||
|
|
||||
LL | let binary_trivial_empty = BRegex::new("^$");
|
||||
| ^^^^
|
||||
|
|
||||
= help: consider using `str::is_empty`
|
||||
|
||||
error: aborting due to 23 previous errors
|
||||
error: aborting due to 24 previous errors
|
||||
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
#![allow(clippy::module_name_repetitions)]
|
||||
#![allow(clippy::recursive_format_impl)]
|
||||
#![allow(clippy::invisible_characters)]
|
||||
#![allow(suspicious_double_ref_op)]
|
||||
#![allow(cast_ref_to_mut)]
|
||||
#![allow(suspicious_double_ref_op)]
|
||||
#![allow(drop_bounds)]
|
||||
#![allow(dropping_copy_types)]
|
||||
#![allow(dropping_references)]
|
||||
|
@ -44,7 +44,6 @@
|
|||
#![allow(enum_intrinsics_non_enums)]
|
||||
#![allow(non_fmt_panics)]
|
||||
#![allow(named_arguments_used_positionally)]
|
||||
#![allow(suspicious_double_ref_op)]
|
||||
#![allow(temporary_cstring_as_ptr)]
|
||||
#![allow(unknown_lints)]
|
||||
#![allow(unused_labels)]
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
#![allow(clippy::module_name_repetitions)]
|
||||
#![allow(clippy::recursive_format_impl)]
|
||||
#![allow(clippy::invisible_characters)]
|
||||
#![allow(suspicious_double_ref_op)]
|
||||
#![allow(cast_ref_to_mut)]
|
||||
#![allow(suspicious_double_ref_op)]
|
||||
#![allow(drop_bounds)]
|
||||
#![allow(dropping_copy_types)]
|
||||
#![allow(dropping_references)]
|
||||
|
@ -44,7 +44,6 @@
|
|||
#![allow(enum_intrinsics_non_enums)]
|
||||
#![allow(non_fmt_panics)]
|
||||
#![allow(named_arguments_used_positionally)]
|
||||
#![allow(suspicious_double_ref_op)]
|
||||
#![allow(temporary_cstring_as_ptr)]
|
||||
#![allow(unknown_lints)]
|
||||
#![allow(unused_labels)]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
|
||||
--> $DIR/rename.rs:51:9
|
||||
--> $DIR/rename.rs:50:9
|
||||
|
|
||||
LL | #![warn(clippy::almost_complete_letter_range)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
|
||||
|
@ -7,295 +7,295 @@ LL | #![warn(clippy::almost_complete_letter_range)]
|
|||
= note: `-D renamed-and-removed-lints` implied by `-D warnings`
|
||||
|
||||
error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
|
||||
--> $DIR/rename.rs:52:9
|
||||
--> $DIR/rename.rs:51:9
|
||||
|
|
||||
LL | #![warn(clippy::blacklisted_name)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
|
||||
|
||||
error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
|
||||
--> $DIR/rename.rs:53:9
|
||||
--> $DIR/rename.rs:52: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:54:9
|
||||
--> $DIR/rename.rs:53: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:55:9
|
||||
--> $DIR/rename.rs:54: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:56:9
|
||||
--> $DIR/rename.rs:55: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:57:9
|
||||
--> $DIR/rename.rs:56:9
|
||||
|
|
||||
LL | #![warn(clippy::cyclomatic_complexity)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
|
||||
|
||||
error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
|
||||
--> $DIR/rename.rs:58:9
|
||||
--> $DIR/rename.rs:57:9
|
||||
|
|
||||
LL | #![warn(clippy::derive_hash_xor_eq)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
|
||||
|
||||
error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
|
||||
--> $DIR/rename.rs:59:9
|
||||
--> $DIR/rename.rs:58: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:60:9
|
||||
--> $DIR/rename.rs:59: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:61:9
|
||||
--> $DIR/rename.rs:60:9
|
||||
|
|
||||
LL | #![warn(clippy::eval_order_dependence)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
|
||||
|
||||
error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
|
||||
--> $DIR/rename.rs:62:9
|
||||
--> $DIR/rename.rs:61: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:63:9
|
||||
--> $DIR/rename.rs:62:9
|
||||
|
|
||||
LL | #![warn(clippy::if_let_some_result)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
|
||||
|
||||
error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
|
||||
--> $DIR/rename.rs:64:9
|
||||
--> $DIR/rename.rs:63:9
|
||||
|
|
||||
LL | #![warn(clippy::integer_arithmetic)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
|
||||
|
||||
error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
|
||||
--> $DIR/rename.rs:65:9
|
||||
--> $DIR/rename.rs:64: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:66:9
|
||||
--> $DIR/rename.rs:65: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:67:9
|
||||
--> $DIR/rename.rs:66: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:68:9
|
||||
--> $DIR/rename.rs:67: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:69:9
|
||||
--> $DIR/rename.rs:68: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:70:9
|
||||
--> $DIR/rename.rs:69: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:71:9
|
||||
--> $DIR/rename.rs:70: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:72:9
|
||||
--> $DIR/rename.rs:71: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:73:9
|
||||
--> $DIR/rename.rs:72: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:74:9
|
||||
--> $DIR/rename.rs:73: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:75:9
|
||||
--> $DIR/rename.rs:74: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:76:9
|
||||
--> $DIR/rename.rs:75: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:77:9
|
||||
--> $DIR/rename.rs:76: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:78:9
|
||||
--> $DIR/rename.rs:77: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:79:9
|
||||
--> $DIR/rename.rs:78:9
|
||||
|
|
||||
LL | #![warn(clippy::zero_width_space)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
|
||||
|
||||
error: lint `clippy::cast_ref_to_mut` has been renamed to `cast_ref_to_mut`
|
||||
--> $DIR/rename.rs:80:9
|
||||
--> $DIR/rename.rs:79:9
|
||||
|
|
||||
LL | #![warn(clippy::cast_ref_to_mut)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `cast_ref_to_mut`
|
||||
|
||||
error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
|
||||
--> $DIR/rename.rs:81:9
|
||||
--> $DIR/rename.rs:80:9
|
||||
|
|
||||
LL | #![warn(clippy::clone_double_ref)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
|
||||
|
||||
error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
|
||||
--> $DIR/rename.rs:82:9
|
||||
--> $DIR/rename.rs:81:9
|
||||
|
|
||||
LL | #![warn(clippy::drop_bounds)]
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
|
||||
|
||||
error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
|
||||
--> $DIR/rename.rs:83:9
|
||||
--> $DIR/rename.rs:82:9
|
||||
|
|
||||
LL | #![warn(clippy::drop_copy)]
|
||||
| ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
|
||||
|
||||
error: lint `clippy::drop_ref` has been renamed to `dropping_references`
|
||||
--> $DIR/rename.rs:84:9
|
||||
--> $DIR/rename.rs:83:9
|
||||
|
|
||||
LL | #![warn(clippy::drop_ref)]
|
||||
| ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
|
||||
|
||||
error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
|
||||
--> $DIR/rename.rs:85:9
|
||||
--> $DIR/rename.rs:84:9
|
||||
|
|
||||
LL | #![warn(clippy::for_loop_over_option)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
|
||||
|
||||
error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
|
||||
--> $DIR/rename.rs:86:9
|
||||
--> $DIR/rename.rs:85:9
|
||||
|
|
||||
LL | #![warn(clippy::for_loop_over_result)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
|
||||
|
||||
error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
|
||||
--> $DIR/rename.rs:87:9
|
||||
--> $DIR/rename.rs:86:9
|
||||
|
|
||||
LL | #![warn(clippy::for_loops_over_fallibles)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
|
||||
|
||||
error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
|
||||
--> $DIR/rename.rs:88:9
|
||||
--> $DIR/rename.rs:87:9
|
||||
|
|
||||
LL | #![warn(clippy::forget_copy)]
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
|
||||
|
||||
error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
|
||||
--> $DIR/rename.rs:89:9
|
||||
--> $DIR/rename.rs:88:9
|
||||
|
|
||||
LL | #![warn(clippy::forget_ref)]
|
||||
| ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
|
||||
|
||||
error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
|
||||
--> $DIR/rename.rs:90:9
|
||||
--> $DIR/rename.rs:89: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:91:9
|
||||
--> $DIR/rename.rs:90: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:92:9
|
||||
--> $DIR/rename.rs:91:9
|
||||
|
|
||||
LL | #![warn(clippy::invalid_ref)]
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
|
||||
|
||||
error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked`
|
||||
--> $DIR/rename.rs:93:9
|
||||
--> $DIR/rename.rs:92:9
|
||||
|
|
||||
LL | #![warn(clippy::invalid_utf8_in_unchecked)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
|
||||
|
||||
error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
|
||||
--> $DIR/rename.rs:94:9
|
||||
--> $DIR/rename.rs:93:9
|
||||
|
|
||||
LL | #![warn(clippy::let_underscore_drop)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
|
||||
|
||||
error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
|
||||
--> $DIR/rename.rs:95:9
|
||||
--> $DIR/rename.rs:94: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:96:9
|
||||
--> $DIR/rename.rs:95:9
|
||||
|
|
||||
LL | #![warn(clippy::panic_params)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
|
||||
|
||||
error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
|
||||
--> $DIR/rename.rs:97:9
|
||||
--> $DIR/rename.rs:96:9
|
||||
|
|
||||
LL | #![warn(clippy::positional_named_format_parameters)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
|
||||
|
||||
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
|
||||
--> $DIR/rename.rs:98:9
|
||||
--> $DIR/rename.rs:97: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:99:9
|
||||
--> $DIR/rename.rs:98: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:100:9
|
||||
--> $DIR/rename.rs:99:9
|
||||
|
|
||||
LL | #![warn(clippy::unused_label)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
|
||||
|
|
209
tests/ui/single_match.fixed
Normal file
209
tests/ui/single_match.fixed
Normal file
|
@ -0,0 +1,209 @@
|
|||
//@run-rustfix
|
||||
#![warn(clippy::single_match)]
|
||||
#![allow(unused, clippy::uninlined_format_args, clippy::redundant_pattern_matching)]
|
||||
fn dummy() {}
|
||||
|
||||
fn single_match() {
|
||||
let x = Some(1u8);
|
||||
|
||||
if let Some(y) = x {
|
||||
println!("{:?}", y);
|
||||
};
|
||||
|
||||
let x = Some(1u8);
|
||||
if let Some(y) = x { println!("{:?}", y) }
|
||||
|
||||
let z = (1u8, 1u8);
|
||||
if let (2..=3, 7..=9) = z { dummy() };
|
||||
|
||||
// Not linted (pattern guards used)
|
||||
match x {
|
||||
Some(y) if y == 0 => println!("{:?}", y),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
// Not linted (no block with statements in the single arm)
|
||||
match z {
|
||||
(2..=3, 7..=9) => println!("{:?}", z),
|
||||
_ => println!("nope"),
|
||||
}
|
||||
}
|
||||
|
||||
enum Foo {
|
||||
Bar,
|
||||
Baz(u8),
|
||||
}
|
||||
use std::borrow::Cow;
|
||||
use Foo::*;
|
||||
|
||||
fn single_match_know_enum() {
|
||||
let x = Some(1u8);
|
||||
let y: Result<_, i8> = Ok(1i8);
|
||||
|
||||
if let Some(y) = x { dummy() };
|
||||
|
||||
if let Ok(y) = y { dummy() };
|
||||
|
||||
let c = Cow::Borrowed("");
|
||||
|
||||
if let Cow::Borrowed(..) = c { dummy() };
|
||||
|
||||
let z = Foo::Bar;
|
||||
// no warning
|
||||
match z {
|
||||
Bar => println!("42"),
|
||||
Baz(_) => (),
|
||||
}
|
||||
|
||||
match z {
|
||||
Baz(_) => println!("42"),
|
||||
Bar => (),
|
||||
}
|
||||
}
|
||||
|
||||
// issue #173
|
||||
fn if_suggestion() {
|
||||
let x = "test";
|
||||
if x == "test" { println!() }
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum Foo {
|
||||
A,
|
||||
B,
|
||||
C(u32),
|
||||
}
|
||||
|
||||
let x = Foo::A;
|
||||
if x == Foo::A { println!() }
|
||||
|
||||
const FOO_C: Foo = Foo::C(0);
|
||||
if x == FOO_C { println!() }
|
||||
|
||||
if x == Foo::A { println!() }
|
||||
|
||||
let x = &x;
|
||||
if x == &Foo::A { println!() }
|
||||
|
||||
enum Bar {
|
||||
A,
|
||||
B,
|
||||
}
|
||||
impl PartialEq for Bar {
|
||||
fn eq(&self, rhs: &Self) -> bool {
|
||||
matches!((self, rhs), (Self::A, Self::A) | (Self::B, Self::B))
|
||||
}
|
||||
}
|
||||
impl Eq for Bar {}
|
||||
|
||||
let x = Bar::A;
|
||||
if let Bar::A = x { println!() }
|
||||
|
||||
// issue #7038
|
||||
struct X;
|
||||
let x = Some(X);
|
||||
if let None = x { println!() };
|
||||
}
|
||||
|
||||
// See: issue #8282
|
||||
fn ranges() {
|
||||
enum E {
|
||||
V,
|
||||
}
|
||||
let x = (Some(E::V), Some(42));
|
||||
|
||||
// Don't lint, because the `E` enum can be extended with additional fields later. Thus, the
|
||||
// proposed replacement to `if let Some(E::V)` may hide non-exhaustive warnings that appeared
|
||||
// because of `match` construction.
|
||||
match x {
|
||||
(Some(E::V), _) => {},
|
||||
(None, _) => {},
|
||||
}
|
||||
|
||||
// lint
|
||||
if let (Some(_), _) = x {}
|
||||
|
||||
// lint
|
||||
if let (Some(E::V), _) = x { todo!() }
|
||||
|
||||
// lint
|
||||
if let (.., Some(E::V), _) = (Some(42), Some(E::V), Some(42)) {}
|
||||
|
||||
// Don't lint, see above.
|
||||
match (Some(E::V), Some(E::V), Some(E::V)) {
|
||||
(.., Some(E::V), _) => {},
|
||||
(.., None, _) => {},
|
||||
}
|
||||
|
||||
// Don't lint, see above.
|
||||
match (Some(E::V), Some(E::V), Some(E::V)) {
|
||||
(Some(E::V), ..) => {},
|
||||
(None, ..) => {},
|
||||
}
|
||||
|
||||
// Don't lint, see above.
|
||||
match (Some(E::V), Some(E::V), Some(E::V)) {
|
||||
(_, Some(E::V), ..) => {},
|
||||
(_, None, ..) => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn skip_type_aliases() {
|
||||
enum OptionEx {
|
||||
Some(i32),
|
||||
None,
|
||||
}
|
||||
enum ResultEx {
|
||||
Err(i32),
|
||||
Ok(i32),
|
||||
}
|
||||
|
||||
use OptionEx::{None, Some};
|
||||
use ResultEx::{Err, Ok};
|
||||
|
||||
// don't lint
|
||||
match Err(42) {
|
||||
Ok(_) => dummy(),
|
||||
Err(_) => (),
|
||||
};
|
||||
|
||||
// don't lint
|
||||
match Some(1i32) {
|
||||
Some(_) => dummy(),
|
||||
None => (),
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! single_match {
|
||||
($num:literal) => {
|
||||
match $num {
|
||||
15 => println!("15"),
|
||||
_ => (),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
single_match!(5);
|
||||
|
||||
// Don't lint
|
||||
let _ = match Some(0) {
|
||||
#[cfg(feature = "foo")]
|
||||
Some(10) => 11,
|
||||
Some(x) => x,
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
|
||||
fn issue_10808(bar: Option<i32>) {
|
||||
if let Some(v) = bar { unsafe {
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
} }
|
||||
|
||||
if let Some(v) = bar {
|
||||
unsafe {
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
//@run-rustfix
|
||||
#![warn(clippy::single_match)]
|
||||
#![allow(clippy::uninlined_format_args)]
|
||||
|
||||
#![allow(unused, clippy::uninlined_format_args, clippy::redundant_pattern_matching)]
|
||||
fn dummy() {}
|
||||
|
||||
fn single_match() {
|
||||
|
@ -244,3 +244,24 @@ fn main() {
|
|||
_ => 0,
|
||||
};
|
||||
}
|
||||
|
||||
fn issue_10808(bar: Option<i32>) {
|
||||
match bar {
|
||||
Some(v) => unsafe {
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
|
||||
match bar {
|
||||
#[rustfmt::skip]
|
||||
Some(v) => {
|
||||
unsafe {
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,5 +155,47 @@ LL | | (..) => {},
|
|||
LL | | }
|
||||
| |_____^ help: try this: `if let (.., Some(E::V), _) = (Some(42), Some(E::V), Some(42)) {}`
|
||||
|
||||
error: aborting due to 16 previous errors
|
||||
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
|
||||
--> $DIR/single_match.rs:249:5
|
||||
|
|
||||
LL | / match bar {
|
||||
LL | | Some(v) => unsafe {
|
||||
LL | | let r = &v as *const i32;
|
||||
LL | | println!("{}", *r);
|
||||
LL | | },
|
||||
LL | | _ => {},
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
help: try this
|
||||
|
|
||||
LL ~ if let Some(v) = bar { unsafe {
|
||||
LL + let r = &v as *const i32;
|
||||
LL + println!("{}", *r);
|
||||
LL + } }
|
||||
|
|
||||
|
||||
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
|
||||
--> $DIR/single_match.rs:257:5
|
||||
|
|
||||
LL | / match bar {
|
||||
LL | | #[rustfmt::skip]
|
||||
LL | | Some(v) => {
|
||||
LL | | unsafe {
|
||||
... |
|
||||
LL | | _ => {},
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
help: try this
|
||||
|
|
||||
LL ~ if let Some(v) = bar {
|
||||
LL + unsafe {
|
||||
LL + let r = &v as *const i32;
|
||||
LL + println!("{}", *r);
|
||||
LL + }
|
||||
LL + }
|
||||
|
|
||||
|
||||
error: aborting due to 18 previous errors
|
||||
|
||||
|
|
173
tests/ui/single_match_else.fixed
Normal file
173
tests/ui/single_match_else.fixed
Normal file
|
@ -0,0 +1,173 @@
|
|||
//@run-rustfix
|
||||
//@aux-build: proc_macros.rs
|
||||
#![warn(clippy::single_match_else)]
|
||||
#![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)]
|
||||
extern crate proc_macros;
|
||||
use proc_macros::with_span;
|
||||
|
||||
enum ExprNode {
|
||||
ExprAddrOf,
|
||||
Butterflies,
|
||||
Unicorns,
|
||||
}
|
||||
|
||||
static NODE: ExprNode = ExprNode::Unicorns;
|
||||
|
||||
fn unwrap_addr() -> Option<&'static ExprNode> {
|
||||
let _ = if let ExprNode::ExprAddrOf = ExprNode::Butterflies { Some(&NODE) } else {
|
||||
let x = 5;
|
||||
None
|
||||
};
|
||||
|
||||
// Don't lint
|
||||
with_span!(span match ExprNode::Butterflies {
|
||||
ExprNode::ExprAddrOf => Some(&NODE),
|
||||
_ => {
|
||||
let x = 5;
|
||||
None
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
macro_rules! unwrap_addr {
|
||||
($expression:expr) => {
|
||||
match $expression {
|
||||
ExprNode::ExprAddrOf => Some(&NODE),
|
||||
_ => {
|
||||
let x = 5;
|
||||
None
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn main() {
|
||||
unwrap_addr!(ExprNode::Unicorns);
|
||||
|
||||
//
|
||||
// don't lint single exprs/statements
|
||||
//
|
||||
|
||||
// don't lint here
|
||||
match Some(1) {
|
||||
Some(a) => println!("${:?}", a),
|
||||
None => return,
|
||||
}
|
||||
|
||||
// don't lint here
|
||||
match Some(1) {
|
||||
Some(a) => println!("${:?}", a),
|
||||
None => {
|
||||
return
|
||||
},
|
||||
}
|
||||
|
||||
// don't lint here
|
||||
match Some(1) {
|
||||
Some(a) => println!("${:?}", a),
|
||||
None => {
|
||||
return;
|
||||
},
|
||||
}
|
||||
|
||||
//
|
||||
// lint multiple exprs/statements "else" blocks
|
||||
//
|
||||
|
||||
// lint here
|
||||
if let Some(a) = Some(1) { println!("${:?}", a) } else {
|
||||
println!("else block");
|
||||
return
|
||||
}
|
||||
|
||||
// lint here
|
||||
if let Some(a) = Some(1) { println!("${:?}", a) } else {
|
||||
println!("else block");
|
||||
return;
|
||||
}
|
||||
|
||||
// lint here
|
||||
use std::convert::Infallible;
|
||||
if let Ok(a) = Result::<i32, Infallible>::Ok(1) { println!("${:?}", a) } else {
|
||||
println!("else block");
|
||||
return;
|
||||
}
|
||||
|
||||
use std::borrow::Cow;
|
||||
if let Cow::Owned(a) = Cow::from("moo") { println!("${:?}", a) } else {
|
||||
println!("else block");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fn issue_10808(bar: Option<i32>) {
|
||||
if let Some(v) = bar { unsafe {
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
} } else {
|
||||
println!("None1");
|
||||
println!("None2");
|
||||
}
|
||||
|
||||
if let Some(v) = bar {
|
||||
println!("Some");
|
||||
println!("{v}");
|
||||
} else { unsafe {
|
||||
let v = 0;
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
} }
|
||||
|
||||
if let Some(v) = bar { unsafe {
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
} } else { unsafe {
|
||||
let v = 0;
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
} }
|
||||
|
||||
if let Some(v) = bar {
|
||||
unsafe {
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
}
|
||||
} else {
|
||||
println!("None");
|
||||
println!("None");
|
||||
}
|
||||
|
||||
match bar {
|
||||
Some(v) => {
|
||||
println!("Some");
|
||||
println!("{v}");
|
||||
},
|
||||
#[rustfmt::skip]
|
||||
None => {
|
||||
unsafe {
|
||||
let v = 0;
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
match bar {
|
||||
#[rustfmt::skip]
|
||||
Some(v) => {
|
||||
unsafe {
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
}
|
||||
},
|
||||
#[rustfmt::skip]
|
||||
None => {
|
||||
unsafe {
|
||||
let v = 0;
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
//@run-rustfix
|
||||
//@aux-build: proc_macros.rs
|
||||
#![warn(clippy::single_match_else)]
|
||||
#![allow(clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)]
|
||||
|
||||
#![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)]
|
||||
extern crate proc_macros;
|
||||
use proc_macros::with_span;
|
||||
|
||||
|
@ -115,3 +115,87 @@ fn main() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn issue_10808(bar: Option<i32>) {
|
||||
match bar {
|
||||
Some(v) => unsafe {
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
},
|
||||
None => {
|
||||
println!("None1");
|
||||
println!("None2");
|
||||
},
|
||||
}
|
||||
|
||||
match bar {
|
||||
Some(v) => {
|
||||
println!("Some");
|
||||
println!("{v}");
|
||||
},
|
||||
None => unsafe {
|
||||
let v = 0;
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
},
|
||||
}
|
||||
|
||||
match bar {
|
||||
Some(v) => unsafe {
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
},
|
||||
None => unsafe {
|
||||
let v = 0;
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
},
|
||||
}
|
||||
|
||||
match bar {
|
||||
#[rustfmt::skip]
|
||||
Some(v) => {
|
||||
unsafe {
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
}
|
||||
},
|
||||
None => {
|
||||
println!("None");
|
||||
println!("None");
|
||||
},
|
||||
}
|
||||
|
||||
match bar {
|
||||
Some(v) => {
|
||||
println!("Some");
|
||||
println!("{v}");
|
||||
},
|
||||
#[rustfmt::skip]
|
||||
None => {
|
||||
unsafe {
|
||||
let v = 0;
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
match bar {
|
||||
#[rustfmt::skip]
|
||||
Some(v) => {
|
||||
unsafe {
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
}
|
||||
},
|
||||
#[rustfmt::skip]
|
||||
None => {
|
||||
unsafe {
|
||||
let v = 0;
|
||||
let r = &v as *const i32;
|
||||
println!("{}", *r);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,5 +100,101 @@ LL + return;
|
|||
LL + }
|
||||
|
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
|
||||
--> $DIR/single_match_else.rs:120:5
|
||||
|
|
||||
LL | / match bar {
|
||||
LL | | Some(v) => unsafe {
|
||||
LL | | let r = &v as *const i32;
|
||||
LL | | println!("{}", *r);
|
||||
... |
|
||||
LL | | },
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
help: try this
|
||||
|
|
||||
LL ~ if let Some(v) = bar { unsafe {
|
||||
LL + let r = &v as *const i32;
|
||||
LL + println!("{}", *r);
|
||||
LL + } } else {
|
||||
LL + println!("None1");
|
||||
LL + println!("None2");
|
||||
LL + }
|
||||
|
|
||||
|
||||
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
|
||||
--> $DIR/single_match_else.rs:131:5
|
||||
|
|
||||
LL | / match bar {
|
||||
LL | | Some(v) => {
|
||||
LL | | println!("Some");
|
||||
LL | | println!("{v}");
|
||||
... |
|
||||
LL | | },
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
help: try this
|
||||
|
|
||||
LL ~ if let Some(v) = bar {
|
||||
LL + println!("Some");
|
||||
LL + println!("{v}");
|
||||
LL + } else { unsafe {
|
||||
LL + let v = 0;
|
||||
LL + let r = &v as *const i32;
|
||||
LL + println!("{}", *r);
|
||||
LL + } }
|
||||
|
|
||||
|
||||
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
|
||||
--> $DIR/single_match_else.rs:143:5
|
||||
|
|
||||
LL | / match bar {
|
||||
LL | | Some(v) => unsafe {
|
||||
LL | | let r = &v as *const i32;
|
||||
LL | | println!("{}", *r);
|
||||
... |
|
||||
LL | | },
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
help: try this
|
||||
|
|
||||
LL ~ if let Some(v) = bar { unsafe {
|
||||
LL + let r = &v as *const i32;
|
||||
LL + println!("{}", *r);
|
||||
LL + } } else { unsafe {
|
||||
LL + let v = 0;
|
||||
LL + let r = &v as *const i32;
|
||||
LL + println!("{}", *r);
|
||||
LL + } }
|
||||
|
|
||||
|
||||
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
|
||||
--> $DIR/single_match_else.rs:155:5
|
||||
|
|
||||
LL | / match bar {
|
||||
LL | | #[rustfmt::skip]
|
||||
LL | | Some(v) => {
|
||||
LL | | unsafe {
|
||||
... |
|
||||
LL | | },
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
help: try this
|
||||
|
|
||||
LL ~ if let Some(v) = bar {
|
||||
LL + unsafe {
|
||||
LL + let r = &v as *const i32;
|
||||
LL + println!("{}", *r);
|
||||
LL + }
|
||||
LL + } else {
|
||||
LL + println!("None");
|
||||
LL + println!("None");
|
||||
LL + }
|
||||
|
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//@aux-build:proc_macro_suspicious_else_formatting.rs
|
||||
|
||||
#![warn(clippy::suspicious_else_formatting)]
|
||||
#![allow(clippy::if_same_then_else, clippy::let_unit_value)]
|
||||
#![allow(clippy::if_same_then_else, clippy::let_unit_value, clippy::needless_else)]
|
||||
|
||||
extern crate proc_macro_suspicious_else_formatting;
|
||||
use proc_macro_suspicious_else_formatting::DeriveBadSpan;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#![warn(clippy::temporary_assignment)]
|
||||
#![allow(const_item_mutation)]
|
||||
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue