Auto merge of #83480 - flip1995:clippyup, r=Dylan-DPC

Update Clippy

Bi-weekly Clippy update.

r? `@Manishearth`
This commit is contained in:
bors 2021-03-26 06:30:16 +00:00
commit 13167029c2
413 changed files with 5720 additions and 2857 deletions

View File

@ -557,18 +557,20 @@ dependencies = [
[[package]]
name = "clippy"
version = "0.1.52"
version = "0.1.53"
dependencies = [
"cargo_metadata 0.12.0",
"clippy-mini-macro-test",
"clippy_lints",
"compiletest_rs 0.6.0",
"derive-new",
"quote",
"regex",
"rustc-workspace-hack",
"rustc_tools_util 0.2.0",
"semver 0.11.0",
"serde",
"syn",
"tempfile",
"tester 0.9.0",
]
@ -579,7 +581,7 @@ version = "0.2.0"
[[package]]
name = "clippy_lints"
version = "0.1.52"
version = "0.1.53"
dependencies = [
"cargo_metadata 0.12.0",
"clippy_utils",
@ -587,13 +589,10 @@ dependencies = [
"itertools 0.9.0",
"pulldown-cmark 0.8.0",
"quine-mc_cluskey",
"quote",
"regex-syntax",
"rustc-semver",
"semver 0.11.0",
"serde",
"smallvec 1.6.1",
"syn",
"toml",
"unicode-normalization",
"url 2.1.1",
@ -601,15 +600,13 @@ dependencies = [
[[package]]
name = "clippy_utils"
version = "0.1.52"
version = "0.1.53"
dependencies = [
"if_chain",
"itertools 0.9.0",
"regex-syntax",
"rustc-semver",
"serde",
"smallvec 1.6.1",
"toml",
"unicode-normalization",
]

View File

@ -2103,6 +2103,7 @@ Released 2018-09-13
[`if_let_some_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_some_result
[`if_not_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_not_else
[`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else
[`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none
[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
[`implicit_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone
[`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher

View File

@ -18,11 +18,13 @@ All contributors are expected to follow the [Rust Code of Conduct].
- [Finding something to fix/improve](#finding-something-to-fiximprove)
- [Writing code](#writing-code)
- [Getting code-completion for rustc internals to work](#getting-code-completion-for-rustc-internals-to-work)
- [IntelliJ Rust](#intellij-rust)
- [Rust Analyzer](#rust-analyzer)
- [How Clippy works](#how-clippy-works)
- [Syncing changes between Clippy and `rust-lang/rust`](#syncing-changes-between-clippy-and-rust-langrust)
- [Syncing changes between Clippy and [`rust-lang/rust`]](#syncing-changes-between-clippy-and-rust-langrust)
- [Patching git-subtree to work with big repos](#patching-git-subtree-to-work-with-big-repos)
- [Performing the sync from `rust-lang/rust` to Clippy](#performing-the-sync-from-rust-langrust-to-clippy)
- [Performing the sync from Clippy to `rust-lang/rust`](#performing-the-sync-from-clippy-to-rust-langrust)
- [Performing the sync from [`rust-lang/rust`] to Clippy](#performing-the-sync-from-rust-langrust-to-clippy)
- [Performing the sync from Clippy to [`rust-lang/rust`]](#performing-the-sync-from-clippy-to-rust-langrust)
- [Defining remotes](#defining-remotes)
- [Issue and PR triage](#issue-and-pr-triage)
- [Bors and Homu](#bors-and-homu)
@ -105,21 +107,41 @@ quick read.
## Getting code-completion for rustc internals to work
Unfortunately, [`rust-analyzer`][ra_homepage] does not (yet?) understand how Clippy uses compiler-internals
### IntelliJ Rust
Unfortunately, [`IntelliJ Rust`][IntelliJ_rust_homepage] does not (yet?) understand how Clippy uses compiler-internals
using `extern crate` and it also needs to be able to read the source files of the rustc-compiler which are not
available via a `rustup` component at the time of writing.
To work around this, you need to have a copy of the [rustc-repo][rustc_repo] available which can be obtained via
`git clone https://github.com/rust-lang/rust/`.
Then you can run a `cargo dev` command to automatically make Clippy use the rustc-repo via path-dependencies
which rust-analyzer will be able to understand.
Run `cargo dev ra_setup --repo-path <repo-path>` where `<repo-path>` is an absolute path to the rustc repo
which `IntelliJ Rust` will be able to understand.
Run `cargo dev ide_setup --repo-path <repo-path>` where `<repo-path>` is a path to the rustc repo
you just cloned.
The command will add path-dependencies pointing towards rustc-crates inside the rustc repo to
Clippys `Cargo.toml`s and should allow rust-analyzer to understand most of the types that Clippy uses.
Just make sure to remove the dependencies again before finally making a pull request!
[ra_homepage]: https://rust-analyzer.github.io/
[rustc_repo]: https://github.com/rust-lang/rust/
[IntelliJ_rust_homepage]: https://intellij-rust.github.io/
### Rust Analyzer
As of [#6869][6869], [`rust-analyzer`][ra_homepage] can understand that Clippy uses compiler-internals
using `extern crate` when `package.metadata.rust-analyzer.rustc_private` is set to `true` in Clippys `Cargo.toml.`
You will required a `nightly` toolchain with the `rustc-dev` component installed.
Make sure that in the `rust-analyzer` configuration, you set
```
{ "rust-analyzer.rustcSource": "discover" }
```
and
```
{ "rust-analyzer.updates.channel": "nightly" }
```
You should be able to see information on things like `Expr` or `EarlyContext` now if you hover them, also
a lot more type hints.
This will work with `rust-analyzer 2021-03-15` shipped in nightly `1.52.0-nightly (107896c32 2021-03-15)` or later.
[ra_homepage]: https://rust-analyzer.github.io/
[6869]: https://github.com/rust-lang/rust-clippy/pull/6869
## How Clippy works

View File

@ -1,6 +1,6 @@
[package]
name = "clippy"
version = "0.1.52"
version = "0.1.53"
authors = ["The Rust Clippy Developers"]
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
repository = "https://github.com/rust-lang/rust-clippy"
@ -37,6 +37,8 @@ clippy-mini-macro-test = { version = "0.2", path = "mini-macro" }
serde = { version = "1.0", features = ["derive"] }
derive-new = "0.5"
regex = "1.4"
quote = "1"
syn = { version = "1", features = ["full"] }
# 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`

View File

@ -90,7 +90,7 @@ pub fn run(check: bool, verbose: bool) {
},
CliError::RaSetupActive => {
eprintln!(
"error: a local rustc repo is enabled as path dependency via `cargo dev ra_setup`.
"error: a local rustc repo is enabled as path dependency via `cargo dev ide_setup`.
Not formatting because that would format the local repo as well!
Please revert the changes to Cargo.tomls first."
);

View File

@ -55,7 +55,7 @@ fn inject_deps_into_manifest(
// do not inject deps if we have aleady done so
if cargo_toml.contains("[target.'cfg(NOT_A_PLATFORM)'.dependencies]") {
eprintln!(
"cargo dev ra_setup: warning: deps already found inside {}, doing nothing.",
"cargo dev ide_setup: warning: deps already found inside {}, doing nothing.",
manifest_path
);
return Ok(());

View File

@ -12,8 +12,8 @@ use walkdir::WalkDir;
pub mod bless;
pub mod fmt;
pub mod ide_setup;
pub mod new_lint;
pub mod ra_setup;
pub mod serve;
pub mod stderr_length_check;
pub mod update_lints;

View File

@ -1,7 +1,7 @@
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
use clap::{App, Arg, ArgMatches, SubCommand};
use clippy_dev::{bless, fmt, new_lint, ra_setup, serve, stderr_length_check, update_lints};
use clippy_dev::{bless, fmt, ide_setup, new_lint, serve, stderr_length_check, update_lints};
fn main() {
let matches = get_clap_config();
@ -34,7 +34,7 @@ fn main() {
("limit_stderr_length", _) => {
stderr_length_check::check();
},
("ra_setup", Some(matches)) => ra_setup::run(matches.value_of("rustc-repo-path")),
("ide_setup", Some(matches)) => ide_setup::run(matches.value_of("rustc-repo-path")),
("serve", Some(matches)) => {
let port = matches.value_of("port").unwrap().parse().unwrap();
let lint = matches.value_of("lint");
@ -138,8 +138,8 @@ fn get_clap_config<'a>() -> ArgMatches<'a> {
.about("Ensures that stderr files do not grow longer than a certain amount of lines."),
)
.subcommand(
SubCommand::with_name("ra_setup")
.about("Alter dependencies so rust-analyzer can find rustc internals")
SubCommand::with_name("ide_setup")
.about("Alter dependencies so Intellij Rust can find rustc internals")
.arg(
Arg::with_name("rustc-repo-path")
.long("repo-path")

View File

@ -1,7 +1,7 @@
[package]
name = "clippy_lints"
# begin automatic update
version = "0.1.52"
version = "0.1.53"
# end automatic update
authors = ["The Rust Clippy Developers"]
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
@ -20,7 +20,6 @@ pulldown-cmark = { version = "0.8", default-features = false }
quine-mc_cluskey = "0.2.2"
regex-syntax = "0.6"
serde = { version = "1.0", features = ["derive"] }
smallvec = { version = "1", features = ["union"] }
toml = "0.5.3"
unicode-normalization = "0.1"
semver = "0.11"
@ -28,8 +27,6 @@ rustc-semver = "1.1.0"
# NOTE: cargo requires serde feat in its url dep
# see <https://github.com/rust-lang/rust/pull/63587#issuecomment-522343864>
url = { version = "2.1.0", features = ["serde"] }
quote = "1"
syn = { version = "1", features = ["full"] }
[features]
deny-warnings = []

View File

@ -1,4 +1,4 @@
use crate::utils::span_lint;
use clippy_utils::diagnostics::span_lint;
use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};

View File

@ -1,5 +1,5 @@
use crate::consts::constant_simple;
use crate::utils::span_lint;
use clippy_utils::diagnostics::span_lint;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};

View File

@ -1,10 +1,9 @@
use clippy_utils::diagnostics::span_lint_and_help;
use rustc_ast::ast::{Expr, ExprKind};
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use crate::utils::span_lint_and_help;
declare_clippy_lint! {
/// **What it does:** Checks for usage of `as` conversions.
///

View File

@ -1,6 +1,6 @@
use std::fmt;
use crate::utils::span_lint_and_help;
use clippy_utils::diagnostics::span_lint_and_help;
use rustc_ast::ast::{Expr, ExprKind, InlineAsmOptions};
use rustc_lint::{EarlyContext, EarlyLintPass, Lint};
use rustc_session::{declare_lint_pass, declare_tool_lint};

View File

@ -1,5 +1,7 @@
use crate::consts::{constant, Constant};
use crate::utils::{is_direct_expn_of, is_expn_of, match_panic_call, snippet_opt, span_lint_and_help};
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::source::snippet_opt;
use clippy_utils::{is_direct_expn_of, is_expn_of, match_panic_call};
use if_chain::if_chain;
use rustc_hir::{Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};

View File

@ -1,7 +1,8 @@
use crate::utils::{
eq_expr_value, get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, trait_ref_of_method,
};
use crate::utils::{higher, sugg};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::implements_trait;
use clippy_utils::{eq_expr_value, get_trait_def_id, trait_ref_of_method};
use clippy_utils::{higher, paths, sugg};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
@ -92,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for AssignOps {
$($trait_name:ident),+) => {
match $op {
$(hir::BinOpKind::$trait_name => {
let [krate, module] = crate::utils::paths::OPS_MODULE;
let [krate, module] = paths::OPS_MODULE;
let path: [&str; 3] = [krate, module, concat!(stringify!($trait_name), "Assign")];
let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) {
trait_id

View File

@ -1,4 +1,6 @@
use crate::utils::{implements_trait, snippet, span_lint_and_then};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
use clippy_utils::ty::implements_trait;
use rustc_errors::Applicability;
use rustc_hir::{AsyncGeneratorKind, Body, BodyId, ExprKind, GeneratorKind, QPath};
use rustc_lint::{LateContext, LateLintPass};

View File

@ -1,4 +1,5 @@
use crate::utils::{match_def_path, span_lint_and_help};
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::match_def_path;
use if_chain::if_chain;
use rustc_hir::def_id::DefId;
use rustc_hir::{Expr, ExprKind};

View File

@ -1,9 +1,8 @@
//! checks for attributes
use crate::utils::{
first_line_of_span, is_present_in_source, match_panic_def_id, snippet_opt, span_lint, span_lint_and_help,
span_lint_and_sugg, span_lint_and_then, without_block_comments,
};
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::match_panic_def_id;
use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments};
use if_chain::if_chain;
use rustc_ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
use rustc_errors::Applicability;
@ -431,7 +430,7 @@ fn is_relevant_block(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_
|stmt| match &stmt.kind {
StmtKind::Local(_) => true,
StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(cx, typeck_results, expr),
_ => false,
StmtKind::Item(_) => false,
},
)
}
@ -565,7 +564,7 @@ fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute) {
// check for `rustfmt_skip` and `rustfmt::skip`
if let Some(skip_item) = &items[1].meta_item();
if skip_item.has_name(sym!(rustfmt_skip)) ||
skip_item.path.segments.last().expect("empty path in attribute").ident.name == sym!(skip);
skip_item.path.segments.last().expect("empty path in attribute").ident.name == sym::skip;
// Only lint outer attributes, because custom inner attributes are unstable
// Tracking issue: https://github.com/rust-lang/rust/issues/54726
if let AttrStyle::Outer = attr.style;
@ -614,7 +613,7 @@ fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) {
}
}
},
_ => {},
MetaItemKind::NameValue(..) => {},
}
}
}

View File

@ -1,4 +1,5 @@
use crate::utils::{match_def_path, paths, span_lint_and_note};
use clippy_utils::diagnostics::span_lint_and_note;
use clippy_utils::{match_def_path, paths};
use rustc_hir::def_id::DefId;
use rustc_hir::{AsyncGeneratorKind, Body, BodyId, GeneratorKind};
use rustc_lint::{LateContext, LateLintPass};

View File

@ -1,6 +1,6 @@
use crate::consts::{constant, Constant};
use crate::utils::sugg::Sugg;
use crate::utils::{span_lint, span_lint_and_then};
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
use clippy_utils::sugg::Sugg;
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;

View File

@ -1,4 +1,4 @@
use crate::utils::span_lint;
use clippy_utils::diagnostics::span_lint;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::{Pat, PatKind};
use rustc_lint::{LateContext, LateLintPass};

View File

@ -1,7 +1,7 @@
use crate::utils::{
differing_macro_contexts, get_parent_expr, get_trait_def_id, implements_trait, paths,
snippet_block_with_applicability, span_lint, span_lint_and_sugg,
};
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
use clippy_utils::source::snippet_block_with_applicability;
use clippy_utils::ty::implements_trait;
use clippy_utils::{differing_macro_contexts, get_parent_expr};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
@ -10,6 +10,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::map::Map;
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
declare_clippy_lint! {
/// **What it does:** Checks for `if` conditions that use blocks containing an
@ -61,7 +62,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
if let Some(parent) = get_parent_expr(self.cx, expr);
if let ExprKind::MethodCall(_, _, args, _) = parent.kind;
let caller = self.cx.typeck_results().expr_ty(&args[0]);
if let Some(iter_id) = get_trait_def_id(self.cx, &paths::ITERATOR);
if let Some(iter_id) = self.cx.tcx.get_diagnostic_item(sym::Iterator);
if implements_trait(self.cx, caller, iter_id, &[]);
then {
return;

View File

@ -1,7 +1,7 @@
use crate::utils::{
eq_expr_value, get_trait_def_id, implements_trait, in_macro, is_type_diagnostic_item, paths, snippet_opt,
span_lint_and_sugg, span_lint_and_then,
};
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{eq_expr_value, get_trait_def_id, in_macro, paths};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;

View File

@ -1,6 +1,7 @@
use crate::utils::{
contains_name, get_pat_name, match_type, paths, single_segment_path, snippet_with_applicability, span_lint_and_sugg,
};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::match_type;
use clippy_utils::{contains_name, get_pat_name, paths, single_segment_path};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, UnOp};

View File

@ -2,7 +2,8 @@
use std::path::PathBuf;
use crate::utils::{run_lints, span_lint};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::run_lints;
use rustc_hir::{hir_id::CRATE_HIR_ID, Crate};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};

View File

@ -1,4 +1,4 @@
use crate::utils::span_lint_and_help;
use clippy_utils::diagnostics::span_lint_and_help;
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_hir::{Expr, ExprKind, PathSegment};

View File

@ -1,10 +1,12 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::in_constant;
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::is_isize_or_usize;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, FloatTy, Ty};
use crate::utils::{in_constant, is_isize_or_usize, snippet_opt, span_lint_and_sugg};
use super::{utils, CAST_LOSSLESS};
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {

View File

@ -1,9 +1,9 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::is_isize_or_usize;
use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty::{self, FloatTy, Ty};
use crate::utils::{is_isize_or_usize, span_lint};
use super::{utils, CAST_POSSIBLE_TRUNCATION};
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {

View File

@ -1,9 +1,9 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::is_isize_or_usize;
use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty::Ty;
use crate::utils::{is_isize_or_usize, span_lint};
use super::{utils, CAST_POSSIBLE_WRAP};
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {

View File

@ -1,9 +1,9 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::is_isize_or_usize;
use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty::{self, FloatTy, Ty};
use crate::utils::{is_isize_or_usize, span_lint};
use super::{utils, CAST_PRECISION_LOSS};
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {

View File

@ -1,13 +1,12 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::is_hir_ty_cfg_dependant;
use if_chain::if_chain;
use rustc_hir::{Expr, ExprKind, GenericArg};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty};
use rustc_span::symbol::sym;
use rustc_target::abi::LayoutOf;
use if_chain::if_chain;
use crate::utils::{is_hir_ty_cfg_dependant, span_lint};
use super::CAST_PTR_ALIGNMENT;
pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {

View File

@ -1,11 +1,9 @@
use clippy_utils::diagnostics::span_lint;
use if_chain::if_chain;
use rustc_hir::{Expr, ExprKind, MutTy, Mutability, TyKind, UnOp};
use rustc_lint::LateContext;
use rustc_middle::ty;
use if_chain::if_chain;
use crate::utils::span_lint;
use super::CAST_REF_TO_MUT;
pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {

View File

@ -1,12 +1,11 @@
use crate::consts::{constant, Constant};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::{method_chain_args, sext};
use if_chain::if_chain;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty};
use if_chain::if_chain;
use crate::consts::{constant, Constant};
use crate::utils::{method_chain_args, sext, span_lint};
use super::CAST_SIGN_LOSS;
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {

View File

@ -1,13 +1,12 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_with_applicability;
use if_chain::if_chain;
use rustc_ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, UintTy};
use if_chain::if_chain;
use crate::utils::{snippet_with_applicability, span_lint_and_then};
use super::CHAR_LIT_AS_U8;
pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {

View File

@ -1,10 +1,10 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use rustc_errors::Applicability;
use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty, UintTy};
use crate::utils::{snippet_with_applicability, span_lint_and_sugg};
use super::{utils, FN_TO_NUMERIC_CAST};
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {

View File

@ -1,10 +1,10 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use rustc_errors::Applicability;
use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty};
use crate::utils::{snippet_with_applicability, span_lint_and_sugg};
use super::{utils, FN_TO_NUMERIC_CAST_WITH_TRUNCATION};
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {

View File

@ -12,14 +12,13 @@ mod ptr_as_ptr;
mod unnecessary_cast;
mod utils;
use clippy_utils::is_hir_ty_cfg_dependant;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use crate::utils::is_hir_ty_cfg_dependant;
declare_clippy_lint! {
/// **What it does:** Checks for casts from any numerical to a float type where
/// the receiving type cannot store all values from the original type without

View File

@ -1,16 +1,15 @@
use std::borrow::Cow;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::meets_msrv;
use clippy_utils::sugg::Sugg;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, Mutability, TyKind};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, TypeAndMut};
use rustc_semver::RustcVersion;
use if_chain::if_chain;
use crate::utils::sugg::Sugg;
use crate::utils::{meets_msrv, span_lint_and_sugg};
use super::PTR_AS_PTR;
const PTR_AS_PTR_MSRV: RustcVersion = RustcVersion::new(1, 38, 0);

View File

@ -1,3 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::numeric_literal::NumericLiteral;
use clippy_utils::source::snippet_opt;
use if_chain::if_chain;
use rustc_ast::{LitFloatType, LitIntType, LitKind};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, Lit, UnOp};
@ -5,10 +9,6 @@ use rustc_lint::{LateContext, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::{self, FloatTy, InferTy, Ty};
use if_chain::if_chain;
use crate::utils::{numeric_literal::NumericLiteral, snippet_opt, span_lint, span_lint_and_sugg};
use super::UNNECESSARY_CAST;
pub(super) fn check(
@ -44,9 +44,18 @@ pub(super) fn check(
lint_unnecessary_cast(cx, expr, &literal_str, cast_from, cast_to);
},
LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed) => {},
LitKind::Int(_, LitIntType::Signed(_) | LitIntType::Unsigned(_))
| LitKind::Float(_, LitFloatType::Suffixed(_))
if cast_from.kind() == cast_to.kind() =>
{
if let Some(src) = snippet_opt(cx, lit.span) {
let num_lit = NumericLiteral::from_lit_kind(&src, &lit.node).unwrap();
lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to);
}
},
_ => {
if cast_from.kind() == cast_to.kind() && !in_external_macro(cx.sess(), expr.span) {
span_lint(
span_lint_and_sugg(
cx,
UNNECESSARY_CAST,
expr.span,
@ -54,6 +63,9 @@ pub(super) fn check(
"casting to the same type is unnecessary (`{}` -> `{}`)",
cast_from, cast_to
),
"try",
literal_str,
Applicability::MachineApplicable,
);
return true;
}

View File

@ -1,5 +1,8 @@
//! lint on manually implemented checked conversions that could be transformed into `try_from`
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{meets_msrv, SpanlessEq};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
@ -9,8 +12,6 @@ use rustc_middle::lint::in_external_macro;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use crate::utils::{meets_msrv, snippet_with_applicability, span_lint_and_sugg, SpanlessEq};
const CHECKED_CONVERSIONS_MSRV: RustcVersion = RustcVersion::new(1, 34, 0);
declare_clippy_lint! {

View File

@ -1,5 +1,9 @@
//! calculate cognitive complexity and warn about overly complex functions
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::LimitStack;
use rustc_ast::ast::Attribute;
use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor};
use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId};
@ -9,8 +13,6 @@ use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Span;
use rustc_span::{sym, BytePos};
use crate::utils::{is_type_diagnostic_item, snippet_opt, span_lint_and_help, LimitStack};
declare_clippy_lint! {
/// **What it does:** Checks for methods with high cognitive complexity.
///

View File

@ -12,15 +12,15 @@
//!
//! This lint is **warn** by default
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::{snippet_block, snippet_block_with_applicability};
use clippy_utils::sugg::Sugg;
use if_chain::if_chain;
use rustc_ast::ast;
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use crate::utils::sugg::Sugg;
use crate::utils::{snippet_block, snippet_block_with_applicability, span_lint_and_sugg, span_lint_and_then};
use rustc_errors::Applicability;
declare_clippy_lint! {
/// **What it does:** Checks for nested `if` statements which can be collapsed
/// by `&&`-combining their conditions.

View File

@ -1,5 +1,6 @@
use crate::utils::visitors::LocalUsedVisitor;
use crate::utils::{path_to_local, span_lint_and_then, SpanlessEq};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::visitors::LocalUsedVisitor;
use clippy_utils::{path_to_local, SpanlessEq};
use if_chain::if_chain;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind, QPath, StmtKind, UnOp};

View File

@ -1,6 +1,6 @@
use crate::utils::{
get_trait_def_id, if_sequence, implements_trait, parent_node_is_if_expr, paths, span_lint_and_help, SpanlessEq,
};
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::implements_trait;
use clippy_utils::{get_trait_def_id, if_sequence, parent_node_is_if_expr, paths, SpanlessEq};
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};

View File

@ -1,5 +1,6 @@
use crate::utils::{eq_expr_value, in_macro, search_same, SpanlessEq, SpanlessHash};
use crate::utils::{get_parent_expr, if_sequence, span_lint_and_note};
use clippy_utils::diagnostics::span_lint_and_note;
use clippy_utils::{eq_expr_value, in_macro, search_same, SpanlessEq, SpanlessHash};
use clippy_utils::{get_parent_expr, if_sequence};
use rustc_hir::{Block, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};

View File

@ -1,7 +1,11 @@
use crate::utils::{is_copy, match_path, paths, span_lint_and_note};
use clippy_utils::diagnostics::span_lint_and_note;
use clippy_utils::ty::is_copy;
use rustc_hir::{Impl, Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
use if_chain::if_chain;
declare_clippy_lint! {
/// **What it does:** Checks for types that implement `Copy` as well as
@ -33,14 +37,16 @@ declare_lint_pass!(CopyIterator => [COPY_ITERATOR]);
impl<'tcx> LateLintPass<'tcx> for CopyIterator {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if let ItemKind::Impl(Impl {
of_trait: Some(ref trait_ref),
..
}) = item.kind
{
if_chain! {
if let ItemKind::Impl(Impl {
of_trait: Some(ref trait_ref),
..
}) = item.kind;
let ty = cx.tcx.type_of(item.def_id);
if is_copy(cx, ty) && match_path(&trait_ref.path, &paths::ITERATOR) {
if is_copy(cx, ty);
if let Some(trait_id) = trait_ref.trait_def_id();
if cx.tcx.is_diagnostic_item(sym::Iterator, trait_id);
then {
span_lint_and_note(
cx,
COPY_ITERATOR,

View File

@ -1,4 +1,6 @@
use crate::utils::{match_def_path, paths, snippet, span_lint_and_sugg};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
use clippy_utils::{match_def_path, paths};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};

View File

@ -1,4 +1,5 @@
use crate::utils::{snippet_opt, span_lint_and_help, span_lint_and_sugg};
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
use clippy_utils::source::snippet_opt;
use rustc_ast::ast;
use rustc_ast::tokenstream::TokenStream;
use rustc_errors::Applicability;

View File

@ -1,7 +1,6 @@
use crate::utils::{
any_parent_is_automatically_derived, contains_name, match_def_path, paths, snippet_with_macro_callsite,
};
use crate::utils::{span_lint_and_note, span_lint_and_sugg};
use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
use clippy_utils::source::snippet_with_macro_callsite;
use clippy_utils::{any_parent_is_automatically_derived, contains_name, match_def_path, paths};
use if_chain::if_chain;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
@ -105,6 +104,7 @@ impl LateLintPass<'_> for Default {
}
}
#[allow(clippy::too_many_lines)]
fn check_block<'tcx>(&mut self, cx: &LateContext<'tcx>, block: &Block<'tcx>) {
// start from the `let mut _ = _::default();` and look at all the following
// statements, see if they re-assign the fields of the binding
@ -198,6 +198,24 @@ impl LateLintPass<'_> for Default {
.collect::<Vec<String>>()
.join(", ");
// give correct suggestion if generics are involved (see #6944)
let binding_type = if_chain! {
if let ty::Adt(adt_def, substs) = binding_type.kind();
if !substs.is_empty();
let adt_def_ty_name = cx.tcx.item_name(adt_def.did);
let generic_args = substs.iter().collect::<Vec<_>>();
let tys_str = generic_args
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(", ");
then {
format!("{}::<{}>", adt_def_ty_name, &tys_str)
} else {
binding_type.to_string()
}
};
let sugg = if ext_with_default {
if field_list.is_empty() {
format!("{}::default()", binding_type)

View File

@ -1,3 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
use if_chain::if_chain;
use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
use rustc_errors::Applicability;
use rustc_hir::{
@ -11,10 +14,6 @@ use rustc_middle::{
};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use if_chain::if_chain;
use crate::utils::{snippet, span_lint_and_sugg};
declare_clippy_lint! {
/// **What it does:** Checks for usage of unconstrained numeric literals which may cause default numeric fallback in type
/// inference.

View File

@ -1,11 +1,14 @@
use crate::utils::{get_parent_expr, implements_trait, snippet, span_lint_and_sugg};
use if_chain::if_chain;
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX, PREC_PREFIX};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::peel_mid_ty_refs;
use clippy_utils::{get_parent_node, in_macro, is_allowed};
use rustc_ast::util::parser::PREC_PREFIX;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use rustc_middle::ty::{self, Ty, TyCtxt, TyS, TypeckResults};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{symbol::sym, Span};
declare_clippy_lint! {
/// **What it does:** Checks for explicit `deref()` or `deref_mut()` method calls.
@ -34,76 +37,265 @@ declare_clippy_lint! {
"Explicit use of deref or deref_mut method while not in a method chain."
}
declare_lint_pass!(Dereferencing => [
EXPLICIT_DEREF_METHODS
impl_lint_pass!(Dereferencing => [
EXPLICIT_DEREF_METHODS,
]);
#[derive(Default)]
pub struct Dereferencing {
state: Option<(State, StateData)>,
// While parsing a `deref` method call in ufcs form, the path to the function is itself an
// expression. This is to store the id of that expression so it can be skipped when
// `check_expr` is called for it.
skip_expr: Option<HirId>,
}
struct StateData {
/// Span of the top level expression
span: Span,
/// The required mutability
target_mut: Mutability,
}
enum State {
// Any number of deref method calls.
DerefMethod {
// The number of calls in a sequence which changed the referenced type
ty_changed_count: usize,
is_final_ufcs: bool,
},
}
// A reference operation considered by this lint pass
enum RefOp {
Method(Mutability),
Deref,
AddrOf,
}
impl<'tcx> LateLintPass<'tcx> for Dereferencing {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if_chain! {
if !expr.span.from_expansion();
if let ExprKind::MethodCall(ref method_name, _, ref args, _) = &expr.kind;
if args.len() == 1;
// Skip path expressions from deref calls. e.g. `Deref::deref(e)`
if Some(expr.hir_id) == self.skip_expr.take() {
return;
}
then {
if let Some(parent_expr) = get_parent_expr(cx, expr) {
// Check if we have the whole call chain here
if let ExprKind::MethodCall(..) = parent_expr.kind {
return;
}
// Check for Expr that we don't want to be linted
let precedence = parent_expr.precedence();
match precedence {
// Lint a Call is ok though
ExprPrecedence::Call | ExprPrecedence::AddrOf => (),
_ => {
if precedence.order() >= PREC_PREFIX && precedence.order() <= PREC_POSTFIX {
return;
}
}
}
}
let name = method_name.ident.as_str();
lint_deref(cx, &*name, &args[0], args[0].span, expr.span);
// Stop processing sub expressions when a macro call is seen
if in_macro(expr.span) {
if let Some((state, data)) = self.state.take() {
report(cx, expr, state, data);
}
return;
}
let typeck = cx.typeck_results();
let (kind, sub_expr) = if let Some(x) = try_parse_ref_op(cx.tcx, typeck, expr) {
x
} else {
// The whole chain of reference operations has been seen
if let Some((state, data)) = self.state.take() {
report(cx, expr, state, data);
}
return;
};
match (self.state.take(), kind) {
(None, kind) => {
let parent = get_parent_node(cx.tcx, expr.hir_id);
let expr_ty = typeck.expr_ty(expr);
match kind {
RefOp::Method(target_mut)
if !is_allowed(cx, EXPLICIT_DEREF_METHODS, expr.hir_id)
&& is_linted_explicit_deref_position(parent, expr.hir_id, expr.span) =>
{
self.state = Some((
State::DerefMethod {
ty_changed_count: if deref_method_same_type(expr_ty, typeck.expr_ty(sub_expr)) {
0
} else {
1
},
is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)),
},
StateData {
span: expr.span,
target_mut,
},
));
}
_ => (),
}
},
(Some((State::DerefMethod { ty_changed_count, .. }, data)), RefOp::Method(_)) => {
self.state = Some((
State::DerefMethod {
ty_changed_count: if deref_method_same_type(typeck.expr_ty(expr), typeck.expr_ty(sub_expr)) {
ty_changed_count
} else {
ty_changed_count + 1
},
is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)),
},
data,
));
},
(Some((state, data)), _) => report(cx, expr, state, data),
}
}
}
fn lint_deref(cx: &LateContext<'_>, method_name: &str, call_expr: &Expr<'_>, var_span: Span, expr_span: Span) {
match method_name {
"deref" => {
let impls_deref_trait = cx.tcx.lang_items().deref_trait().map_or(false, |id| {
implements_trait(cx, cx.typeck_results().expr_ty(&call_expr), id, &[])
});
if impls_deref_trait {
span_lint_and_sugg(
cx,
EXPLICIT_DEREF_METHODS,
expr_span,
"explicit deref method call",
"try this",
format!("&*{}", &snippet(cx, var_span, "..")),
Applicability::MachineApplicable,
);
}
fn try_parse_ref_op(
tcx: TyCtxt<'tcx>,
typeck: &'tcx TypeckResults<'_>,
expr: &'tcx Expr<'_>,
) -> Option<(RefOp, &'tcx Expr<'tcx>)> {
let (def_id, arg) = match expr.kind {
ExprKind::MethodCall(_, _, [arg], _) => (typeck.type_dependent_def_id(expr.hir_id)?, arg),
ExprKind::Call(
Expr {
kind: ExprKind::Path(path),
hir_id,
..
},
[arg],
) => (typeck.qpath_res(path, *hir_id).opt_def_id()?, arg),
ExprKind::Unary(UnOp::Deref, sub_expr) if !typeck.expr_ty(sub_expr).is_unsafe_ptr() => {
return Some((RefOp::Deref, sub_expr));
},
ExprKind::AddrOf(BorrowKind::Ref, _, sub_expr) => return Some((RefOp::AddrOf, sub_expr)),
_ => return None,
};
if tcx.is_diagnostic_item(sym::deref_method, def_id) {
Some((RefOp::Method(Mutability::Not), arg))
} else if tcx.trait_of_item(def_id)? == tcx.lang_items().deref_mut_trait()? {
Some((RefOp::Method(Mutability::Mut), arg))
} else {
None
}
}
// Checks whether the type for a deref call actually changed the type, not just the mutability of
// the reference.
fn deref_method_same_type(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool {
match (result_ty.kind(), arg_ty.kind()) {
(ty::Ref(_, result_ty, _), ty::Ref(_, arg_ty, _)) => TyS::same_type(result_ty, arg_ty),
// The result type for a deref method is always a reference
// Not matching the previous pattern means the argument type is not a reference
// This means that the type did change
_ => false,
}
}
// Checks whether the parent node is a suitable context for switching from a deref method to the
// deref operator.
fn is_linted_explicit_deref_position(parent: Option<Node<'_>>, child_id: HirId, child_span: Span) -> bool {
let parent = match parent {
Some(Node::Expr(e)) if e.span.ctxt() == child_span.ctxt() => e,
_ => return true,
};
match parent.kind {
// Leave deref calls in the middle of a method chain.
// e.g. x.deref().foo()
ExprKind::MethodCall(_, _, [self_arg, ..], _) if self_arg.hir_id == child_id => false,
// Leave deref calls resulting in a called function
// e.g. (x.deref())()
ExprKind::Call(func_expr, _) if func_expr.hir_id == child_id => false,
// Makes an ugly suggestion
// e.g. *x.deref() => *&*x
ExprKind::Unary(UnOp::Deref, _)
// Postfix expressions would require parens
| ExprKind::Match(_, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar)
| ExprKind::Field(..)
| ExprKind::Index(..)
| ExprKind::Err => false,
ExprKind::Box(..)
| ExprKind::ConstBlock(..)
| ExprKind::Array(_)
| ExprKind::Call(..)
| ExprKind::MethodCall(..)
| ExprKind::Tup(..)
| ExprKind::Binary(..)
| ExprKind::Unary(..)
| ExprKind::Lit(..)
| ExprKind::Cast(..)
| ExprKind::Type(..)
| ExprKind::DropTemps(..)
| ExprKind::If(..)
| ExprKind::Loop(..)
| ExprKind::Match(..)
| ExprKind::Closure(..)
| ExprKind::Block(..)
| ExprKind::Assign(..)
| ExprKind::AssignOp(..)
| ExprKind::Path(..)
| ExprKind::AddrOf(..)
| ExprKind::Break(..)
| ExprKind::Continue(..)
| ExprKind::Ret(..)
| ExprKind::InlineAsm(..)
| ExprKind::LlvmInlineAsm(..)
| ExprKind::Struct(..)
| ExprKind::Repeat(..)
| ExprKind::Yield(..) => true,
}
}
#[allow(clippy::needless_pass_by_value)]
fn report(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data: StateData) {
match state {
State::DerefMethod {
ty_changed_count,
is_final_ufcs,
} => {
let mut app = Applicability::MachineApplicable;
let (expr_str, expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app);
let ty = cx.typeck_results().expr_ty(expr);
let (_, ref_count) = peel_mid_ty_refs(ty);
let deref_str = if ty_changed_count >= ref_count && ref_count != 0 {
// a deref call changing &T -> &U requires two deref operators the first time
// this occurs. One to remove the reference, a second to call the deref impl.
"*".repeat(ty_changed_count + 1)
} else {
"*".repeat(ty_changed_count)
};
let addr_of_str = if ty_changed_count < ref_count {
// Check if a reborrow from &mut T -> &T is required.
if data.target_mut == Mutability::Not && matches!(ty.kind(), ty::Ref(_, _, Mutability::Mut)) {
"&*"
} else {
""
}
} else if data.target_mut == Mutability::Mut {
"&mut "
} else {
"&"
};
let expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX {
format!("({})", expr_str)
} else {
expr_str.into_owned()
};
span_lint_and_sugg(
cx,
EXPLICIT_DEREF_METHODS,
data.span,
match data.target_mut {
Mutability::Not => "explicit `deref` method call",
Mutability::Mut => "explicit `deref_mut` method call",
},
"try this",
format!("{}{}{}", addr_of_str, deref_str, expr_str),
app,
);
},
"deref_mut" => {
let impls_deref_mut_trait = cx.tcx.lang_items().deref_mut_trait().map_or(false, |id| {
implements_trait(cx, cx.typeck_results().expr_ty(&call_expr), id, &[])
});
if impls_deref_mut_trait {
span_lint_and_sugg(
cx,
EXPLICIT_DEREF_METHODS,
expr_span,
"explicit deref_mut method call",
"try this",
format!("&mut *{}", &snippet(cx, var_span, "..")),
Applicability::MachineApplicable,
);
}
},
_ => (),
}
}

View File

@ -1,8 +1,7 @@
use crate::utils::paths;
use crate::utils::{
get_trait_def_id, is_allowed, is_automatically_derived, is_copy, match_def_path, span_lint_and_help,
span_lint_and_note, span_lint_and_then,
};
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_then};
use clippy_utils::paths;
use clippy_utils::ty::is_copy;
use clippy_utils::{get_trait_def_id, is_allowed, is_automatically_derived, match_def_path};
use if_chain::if_chain;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, NestedVisitorMap, Visitor};

View File

@ -1,4 +1,5 @@
use crate::utils::{fn_def_id, span_lint};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::fn_def_id;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::Expr;

View File

@ -1,7 +1,6 @@
use crate::utils::{
implements_trait, is_entrypoint_fn, is_expn_of, is_type_diagnostic_item, match_panic_def_id, method_chain_args,
return_ty, span_lint, span_lint_and_note,
};
use clippy_utils::diagnostics::{span_lint, span_lint_and_note};
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{is_entrypoint_fn, is_expn_of, match_panic_def_id, method_chain_args, return_ty};
use if_chain::if_chain;
use itertools::Itertools;
use rustc_ast::ast::{Async, AttrKind, Attribute, FnKind, FnRetTy, ItemKind};
@ -584,7 +583,7 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) {
let returns_nothing = match &sig.decl.output {
FnRetTy::Default(..) => true,
FnRetTy::Ty(ty) if ty.kind.is_unit() => true,
_ => false,
FnRetTy::Ty(_) => false,
};
if returns_nothing && !is_async && !block.stmts.is_empty() {

View File

@ -1,13 +1,14 @@
//! Lint on unnecessary double comparisons. Some examples:
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::eq_expr_value;
use clippy_utils::source::snippet_with_applicability;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use crate::utils::{eq_expr_value, snippet_with_applicability, span_lint_and_sugg};
declare_clippy_lint! {
/// **What it does:** Checks for double comparisons that could be simplified to a single expression.
///

View File

@ -1,4 +1,4 @@
use crate::utils::span_lint;
use clippy_utils::diagnostics::span_lint;
use rustc_ast::ast::{Expr, ExprKind};
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};

View File

@ -1,4 +1,6 @@
use crate::utils::{is_copy, match_def_path, paths, span_lint_and_note};
use clippy_utils::diagnostics::span_lint_and_note;
use clippy_utils::ty::is_copy;
use clippy_utils::{match_def_path, paths};
use if_chain::if_chain;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};

View File

@ -1,3 +1,5 @@
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::match_type;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind};
@ -6,8 +8,8 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Spanned;
use crate::consts::{constant, Constant};
use crate::utils::paths;
use crate::utils::{match_type, snippet_with_applicability, span_lint_and_sugg};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::paths;
declare_clippy_lint! {
/// **What it does:** Checks for calculation of subsecond microseconds or milliseconds

View File

@ -1,12 +1,11 @@
//! Lint on if expressions with an else if, but without a final else branch.
use clippy_utils::diagnostics::span_lint_and_help;
use rustc_ast::ast::{Expr, ExprKind};
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use crate::utils::span_lint_and_help;
declare_clippy_lint! {
/// **What it does:** Checks for usage of if expressions with an `else if` branch,
/// but without a final `else` branch.

View File

@ -1,6 +1,6 @@
//! lint when there is an enum with no variants
use crate::utils::span_lint_and_help;
use clippy_utils::diagnostics::span_lint_and_help;
use rustc_hir::{Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};

View File

@ -1,6 +1,8 @@
use crate::utils::SpanlessEq;
use crate::utils::{get_item_name, is_type_diagnostic_item, match_type, paths, snippet, snippet_opt};
use crate::utils::{snippet_with_applicability, span_lint_and_then};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
use clippy_utils::ty::{is_type_diagnostic_item, match_type};
use clippy_utils::SpanlessEq;
use clippy_utils::{get_item_name, paths};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};

View File

@ -2,7 +2,7 @@
//! don't fit into an `i32`
use crate::consts::{miri_to_const, Constant};
use crate::utils::span_lint;
use clippy_utils::diagnostics::span_lint;
use rustc_hir::{Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::util::IntTypeExt;

View File

@ -1,7 +1,8 @@
//! lint on enum variants that are prefixed or suffixed by the same characters
use crate::utils::{camel_case, is_present_in_source};
use crate::utils::{span_lint, span_lint_and_help};
use clippy_utils::camel_case;
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
use clippy_utils::source::is_present_in_source;
use rustc_ast::ast::{EnumDef, Item, ItemKind, VisibilityKind};
use rustc_lint::{EarlyContext, EarlyLintPass, Lint};
use rustc_session::{declare_tool_lint, impl_lint_pass};

View File

@ -1,7 +1,7 @@
use crate::utils::{
ast_utils::is_useless_with_eq_exprs, eq_expr_value, higher, implements_trait, in_macro, is_copy, is_expn_of,
multispan_sugg, snippet, span_lint, span_lint_and_then,
};
use clippy_utils::diagnostics::{multispan_sugg, span_lint, span_lint_and_then};
use clippy_utils::source::snippet;
use clippy_utils::ty::{implements_trait, is_copy};
use clippy_utils::{ast_utils::is_useless_with_eq_exprs, eq_expr_value, higher, in_macro, is_expn_of};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, StmtKind};

View File

@ -1,10 +1,10 @@
use clippy_utils::diagnostics::span_lint;
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use crate::consts::{constant_simple, Constant};
use crate::utils::span_lint;
declare_clippy_lint! {
/// **What it does:** Checks for erasing operations, e.g., `x * 0`.

View File

@ -1,3 +1,5 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::contains_ty;
use rustc_hir::intravisit;
use rustc_hir::{self, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node};
use rustc_infer::infer::TyCtxtInferExt;
@ -11,8 +13,6 @@ use rustc_target::abi::LayoutOf;
use rustc_target::spec::abi::Abi;
use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
use crate::utils::{contains_ty, span_lint};
#[derive(Copy, Clone)]
pub struct BoxedLocal {
pub too_large_for_stack: u64,
@ -186,7 +186,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
}
}
fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _: HirId) { }
fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _: HirId) {}
}
impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> {

View File

@ -1,3 +1,9 @@
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::higher;
use clippy_utils::higher::VecArgs;
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{implements_trait, type_is_unsafe_function};
use clippy_utils::{is_adjusted, iter_input_pats};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{def_id, Expr, ExprKind, Param, PatKind, QPath};
@ -6,13 +12,6 @@ use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use crate::utils::{
implements_trait, is_adjusted, iter_input_pats, snippet_opt, span_lint_and_sugg, span_lint_and_then,
type_is_unsafe_function,
};
use clippy_utils::higher;
use clippy_utils::higher::VecArgs;
declare_clippy_lint! {
/// **What it does:** Checks for closures which just call another function where
/// the function can be called directly. `unsafe` functions or calls where types

View File

@ -1,4 +1,5 @@
use crate::utils::{get_parent_expr, path_to_local, path_to_local_id, span_lint, span_lint_and_note};
use clippy_utils::diagnostics::{span_lint, span_lint_and_note};
use clippy_utils::{get_parent_expr, path_to_local, path_to_local_id};
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Guard, HirId, Local, Node, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
@ -272,7 +273,7 @@ fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt<'_>) -
.init
.as_ref()
.map_or(StopEarly::KeepGoing, |expr| check_expr(vis, expr)),
_ => StopEarly::KeepGoing,
StmtKind::Item(..) => StopEarly::KeepGoing,
}
}

View File

@ -1,7 +1,6 @@
use crate::utils::{attr_by_name, in_macro, match_path_ast, span_lint_and_help};
use rustc_ast::ast::{
AssocItemKind, Extern, FnKind, FnSig, ImplKind, Item, ItemKind, TraitKind, Ty, TyKind,
};
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::{attr_by_name, in_macro, match_path_ast};
use rustc_ast::ast::{AssocItemKind, Extern, FnKind, FnSig, ImplKind, Item, ItemKind, TraitKind, Ty, TyKind};
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span;

View File

@ -1,4 +1,5 @@
use crate::utils::{indent_of, span_lint_and_then};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::indent_of;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Item, ItemKind};

View File

@ -1,4 +1,5 @@
use crate::utils::{is_entrypoint_fn, match_def_path, paths, span_lint};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::{is_entrypoint_fn, match_def_path, paths};
use if_chain::if_chain;
use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node};
use rustc_lint::{LateContext, LateLintPass};

View File

@ -1,4 +1,5 @@
use crate::utils::{is_expn_of, match_function_call, paths, span_lint, span_lint_and_sugg};
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
use clippy_utils::{is_expn_of, match_function_call, paths};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;

View File

@ -1,4 +1,6 @@
use crate::utils::{is_expn_of, is_type_diagnostic_item, match_panic_def_id, method_chain_args, span_lint_and_then};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{is_expn_of, match_panic_def_id, method_chain_args};
use if_chain::if_chain;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};

View File

@ -1,4 +1,5 @@
use crate::utils::{match_def_path, paths, span_lint_and_then, sugg};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{match_def_path, paths, sugg};
use if_chain::if_chain;
use rustc_ast::util::parser::AssocOp;
use rustc_errors::Applicability;

View File

@ -1,4 +1,5 @@
use crate::utils::{numeric_literal, span_lint_and_sugg};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::numeric_literal;
use if_chain::if_chain;
use rustc_ast::ast::{self, LitFloatType, LitKind};
use rustc_errors::Applicability;

View File

@ -2,7 +2,8 @@ use crate::consts::{
constant, constant_simple, Constant,
Constant::{Int, F32, F64},
};
use crate::utils::{eq_expr_value, get_parent_expr, numeric_literal, span_lint_and_sugg, sugg};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::{eq_expr_value, get_parent_expr, numeric_literal, sugg};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp};

View File

@ -1,8 +1,8 @@
use crate::utils::paths;
use crate::utils::{
is_expn_of, is_type_diagnostic_item, last_path_segment, match_def_path, match_function_call, snippet, snippet_opt,
span_lint_and_then,
};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::paths;
use clippy_utils::source::{snippet, snippet_opt};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{is_expn_of, last_path_segment, match_def_path, match_function_call};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;

View File

@ -1,4 +1,6 @@
use crate::utils::{differing_macro_contexts, snippet_opt, span_lint_and_help, span_lint_and_note};
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note};
use clippy_utils::differing_macro_contexts;
use clippy_utils::source::snippet_opt;
use if_chain::if_chain;
use rustc_ast::ast::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp};
use rustc_lint::{EarlyContext, EarlyLintPass};

View File

@ -1,5 +1,6 @@
use crate::utils::paths::INTO;
use crate::utils::{match_def_path, meets_msrv, span_lint_and_help};
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::paths::INTO;
use clippy_utils::{match_def_path, meets_msrv};
use if_chain::if_chain;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass, LintContext};

View File

@ -1,3 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_type_diagnostic_item;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{def, Expr, ExprKind, PrimTy, QPath, TyKind};
@ -6,10 +9,6 @@ use rustc_middle::ty::Ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::sym;
use crate::utils::is_type_diagnostic_item;
use crate::utils::span_lint_and_sugg;
use crate::utils::sugg::Sugg;
declare_clippy_lint! {
/// **What it does:**
/// Checks for function invocations of the form `primitive::from_str_radix(s, 10)`

View File

@ -1,7 +1,9 @@
use crate::utils::{
attr_by_name, attrs::is_proc_macro, is_must_use_ty, is_trait_impl_item, is_type_diagnostic_item, iter_input_pats,
match_def_path, must_use_attr, path_to_local, return_ty, snippet, snippet_opt, span_lint, span_lint_and_help,
span_lint_and_then, trait_ref_of_method, type_is_unsafe_function,
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then};
use clippy_utils::source::{snippet, snippet_opt};
use clippy_utils::ty::{is_must_use_ty, is_type_diagnostic_item, type_is_unsafe_function};
use clippy_utils::{
attr_by_name, attrs::is_proc_macro, is_trait_impl_item, iter_input_pats, match_def_path, must_use_attr,
path_to_local, return_ty, trait_ref_of_method,
};
use if_chain::if_chain;
use rustc_ast::ast::Attribute;

View File

@ -1,4 +1,5 @@
use crate::utils;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::return_ty;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{Body, FnDecl, HirId};
use rustc_infer::infer::TyCtxtInferExt;
@ -61,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
if let FnKind::Closure = kind {
return;
}
let ret_ty = utils::return_ty(cx, hir_id);
let ret_ty = return_ty(cx, hir_id);
if let Opaque(id, subst) = *ret_ty.kind() {
let preds = cx.tcx.explicit_item_bounds(id);
let mut is_future = false;
@ -84,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
fulfillment_cx.select_all_or_error(&infcx)
});
if let Err(send_errors) = send_result {
utils::span_lint_and_then(
span_lint_and_then(
cx,
FUTURE_NOT_SEND,
span,

View File

@ -1,6 +1,9 @@
//! lint on using `x.get(x.len() - 1)` instead of `x.last()`
use crate::utils::{is_type_diagnostic_item, snippet_with_applicability, span_lint_and_sugg, SpanlessEq};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::SpanlessEq;
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;

View File

@ -1,3 +1,4 @@
use clippy_utils::source::snippet;
use if_chain::if_chain;
use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
@ -6,7 +7,8 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use crate::consts::{constant_simple, Constant};
use crate::utils::{clip, snippet, span_lint, unsext};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::{clip, unsext};
declare_clippy_lint! {
/// **What it does:** Checks for identity operations, e.g., `x + 0`.

View File

@ -1,4 +1,6 @@
use crate::utils::{is_type_diagnostic_item, span_lint_and_help, SpanlessEq};
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::SpanlessEq;
use if_chain::if_chain;
use rustc_hir::intravisit::{self as visit, NestedVisitorMap, Visitor};
use rustc_hir::{Expr, ExprKind, MatchSource};

View File

@ -1,4 +1,7 @@
use crate::utils::{is_type_diagnostic_item, method_chain_args, snippet_with_applicability, span_lint_and_sugg};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::method_chain_args;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_diagnostic_item;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, MatchSource, PatKind, QPath};

View File

@ -1,13 +1,12 @@
//! lint on if branches that could be swapped so no `!` operation is necessary
//! on the condition
use clippy_utils::diagnostics::span_lint_and_help;
use rustc_ast::ast::{BinOpKind, Expr, ExprKind, UnOp};
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use crate::utils::span_lint_and_help;
declare_clippy_lint! {
/// **What it does:** Checks for usage of `!` or `!=` in an if condition with an
/// else branch.

View File

@ -0,0 +1,117 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::source::snippet_with_macro_callsite;
use clippy_utils::{match_qpath, meets_msrv, parent_node_is_if_expr};
use if_chain::if_chain;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
const IF_THEN_SOME_ELSE_NONE_MSRV: RustcVersion = RustcVersion::new(1, 50, 0);
declare_clippy_lint! {
/// **What it does:** Checks for if-else that could be written to `bool::then`.
///
/// **Why is this bad?** Looks a little redundant. Using `bool::then` helps it have less lines of code.
///
/// **Known problems:** None.
///
/// **Example:**
///
/// ```rust
/// # let v = vec![0];
/// let a = if v.is_empty() {
/// println!("true!");
/// Some(42)
/// } else {
/// None
/// };
/// ```
///
/// Could be written:
///
/// ```rust
/// # let v = vec![0];
/// let a = v.is_empty().then(|| {
/// println!("true!");
/// 42
/// });
/// ```
pub IF_THEN_SOME_ELSE_NONE,
restriction,
"Finds if-else that could be written using `bool::then`"
}
pub struct IfThenSomeElseNone {
msrv: Option<RustcVersion>,
}
impl IfThenSomeElseNone {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
Self { msrv }
}
}
impl_lint_pass!(IfThenSomeElseNone => [IF_THEN_SOME_ELSE_NONE]);
impl LateLintPass<'_> for IfThenSomeElseNone {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'tcx Expr<'_>) {
if !meets_msrv(self.msrv.as_ref(), &IF_THEN_SOME_ELSE_NONE_MSRV) {
return;
}
if in_external_macro(cx.sess(), expr.span) {
return;
}
// We only care about the top-most `if` in the chain
if parent_node_is_if_expr(expr, cx) {
return;
}
if_chain! {
if let ExprKind::If(ref cond, ref then, Some(ref els)) = expr.kind;
if let ExprKind::Block(ref then_block, _) = then.kind;
if let Some(ref then_expr) = then_block.expr;
if let ExprKind::Call(ref then_call, [then_arg]) = then_expr.kind;
if let ExprKind::Path(ref then_call_qpath) = then_call.kind;
if match_qpath(then_call_qpath, &clippy_utils::paths::OPTION_SOME);
if let ExprKind::Block(ref els_block, _) = els.kind;
if els_block.stmts.is_empty();
if let Some(ref els_expr) = els_block.expr;
if let ExprKind::Path(ref els_call_qpath) = els_expr.kind;
if match_qpath(els_call_qpath, &clippy_utils::paths::OPTION_NONE);
then {
let cond_snip = snippet_with_macro_callsite(cx, cond.span, "[condition]");
let cond_snip = if matches!(cond.kind, ExprKind::Unary(_, _) | ExprKind::Binary(_, _, _)) {
format!("({})", cond_snip)
} else {
cond_snip.into_owned()
};
let arg_snip = snippet_with_macro_callsite(cx, then_arg.span, "");
let closure_body = if then_block.stmts.is_empty() {
arg_snip.into_owned()
} else {
format!("{{ /* snippet */ {} }}", arg_snip)
};
let help = format!(
"consider using `bool::then` like: `{}.then(|| {})`",
cond_snip,
closure_body,
);
span_lint_and_help(
cx,
IF_THEN_SOME_ELSE_NONE,
expr.span,
"this could be simplified with `bool::then`",
None,
&help,
);
}
}
}
extract_msrv_attr!(LateContext);
}

View File

@ -1,4 +1,6 @@
use crate::utils::{match_panic_def_id, snippet_opt, span_lint_and_then};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::match_panic_def_id;
use clippy_utils::source::snippet_opt;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;

View File

@ -1,4 +1,5 @@
use crate::utils::{in_macro, match_qpath, span_lint_and_sugg, SpanlessEq};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::{in_macro, match_qpath, SpanlessEq};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;

View File

@ -1,3 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
use if_chain::if_chain;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::Applicability;
use rustc_hir::{self as hir, ExprKind};
@ -5,13 +8,10 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::Symbol;
use if_chain::if_chain;
use crate::utils::{snippet, span_lint_and_sugg};
declare_clippy_lint! {
/// **What it does:** Checks for struct constructors where the order of the field init
/// shorthand in the constructor is inconsistent with the order in the struct definition.
/// **What it does:** Checks for struct constructors where all fields are shorthand and
/// the order of the field init shorthand in the constructor is inconsistent
/// with the order in the struct definition.
///
/// **Why is this bad?** Since the order of fields in a constructor doesn't affect the
/// resulted instance as the below example indicates,
@ -25,11 +25,11 @@ declare_clippy_lint! {
/// let x = 1;
/// let y = 2;
///
/// // This assertion never fails.
/// // This assertion never fails:
/// assert_eq!(Foo { x, y }, Foo { y, x });
/// ```
///
/// inconsistent order means nothing and just decreases readability and consistency.
/// inconsistent order can be confusing and decreases readability and consistency.
///
/// **Known problems:** None.
///
@ -42,6 +42,7 @@ declare_clippy_lint! {
/// }
/// let x = 1;
/// let y = 2;
///
/// Foo { y, x };
/// ```
///
@ -107,7 +108,7 @@ impl LateLintPass<'_> for InconsistentStructConstructor {
cx,
INCONSISTENT_STRUCT_CONSTRUCTOR,
expr.span,
"inconsistent struct constructor",
"struct constructor field order is inconsistent with struct definition field order",
"try",
sugg,
Applicability::MachineApplicable,

View File

@ -1,7 +1,8 @@
//! lint on indexing and slicing operations
use crate::consts::{constant, Constant};
use crate::utils::{higher, span_lint, span_lint_and_help};
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
use clippy_utils::higher;
use rustc_ast::ast::RangeLimits;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};

View File

@ -1,9 +1,10 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::{implements_trait, match_type};
use clippy_utils::{get_trait_def_id, higher, match_qpath, paths};
use rustc_hir::{BorrowKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, match_type, paths, span_lint};
declare_clippy_lint! {
/// **What it does:** Checks for iteration that is guaranteed to be infinite.
///

View File

@ -1,6 +1,7 @@
//! lint on inherent implementations
use crate::utils::{in_macro, span_lint_and_then};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::in_macro;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::{def_id, Crate, Impl, Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};

View File

@ -1,14 +1,12 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{get_trait_def_id, paths, return_ty, trait_ref_of_method};
use if_chain::if_chain;
use rustc_hir::{ImplItem, ImplItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
use crate::utils::{
get_trait_def_id, implements_trait, is_type_diagnostic_item, paths, return_ty, span_lint_and_help,
trait_ref_of_method,
};
declare_clippy_lint! {
/// **What it does:** Checks for the definition of inherent methods with a signature of `to_string(&self) -> String`.
///

View File

@ -1,7 +1,7 @@
//! checks for `#[inline]` on trait methods without bodies
use crate::utils::span_lint_and_then;
use crate::utils::sugg::DiagnosticBuilderExt;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::sugg::DiagnosticBuilderExt;
use rustc_ast::ast::Attribute;
use rustc_errors::Applicability;
use rustc_hir::{TraitFn, TraitItem, TraitItemKind};

View File

@ -1,12 +1,12 @@
//! lint on blocks unnecessarily using >= with a + 1 or - 1
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_opt;
use rustc_ast::ast::{BinOpKind, Expr, ExprKind, Lit, LitKind};
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use crate::utils::{snippet_opt, span_lint_and_sugg};
declare_clippy_lint! {
/// **What it does:** Checks for usage of `x >= y + 1` or `x - 1 >= y` (and `<=`) in a block
///

View File

@ -1,4 +1,4 @@
use crate::utils::span_lint_and_help;
use clippy_utils::diagnostics::span_lint_and_help;
use if_chain::if_chain;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};

View File

@ -1,6 +1,6 @@
//! lint when items are used after statements
use crate::utils::span_lint;
use clippy_utils::diagnostics::span_lint;
use rustc_ast::ast::{Block, ItemKind, StmtKind};
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;

View File

@ -1,5 +1,5 @@
use crate::rustc_target::abi::LayoutOf;
use crate::utils::span_lint_and_then;
use clippy_utils::diagnostics::span_lint_and_then;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Item, ItemKind};

Some files were not shown because too many files have changed in this diff Show More