Merge remote-tracking branch 'upstream/master' into rustup

This commit is contained in:
flip1995 2022-02-10 18:11:27 +01:00
commit 0775c06d32
No known key found for this signature in database
GPG key ID: 1CA0DF2AF59D68A5
127 changed files with 4486 additions and 3170 deletions

View file

@ -1,13 +1,12 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{method_chain_args, single_segment_path};
use clippy_utils::{method_chain_args, path_def_id};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_lint::Lint;
use rustc_middle::ty;
use rustc_span::sym;
use rustc_middle::ty::{self, DefIdTree};
/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints.
pub(super) fn check(
@ -19,11 +18,9 @@ pub(super) fn check(
) -> bool {
if_chain! {
if let Some(args) = method_chain_args(info.chain, chain_methods);
if let hir::ExprKind::Call(fun, arg_char) = info.other.kind;
if arg_char.len() == 1;
if let hir::ExprKind::Path(ref qpath) = fun.kind;
if let Some(segment) = single_segment_path(qpath);
if segment.ident.name == sym::Some;
if let hir::ExprKind::Call(fun, [arg_char]) = info.other.kind;
if let Some(id) = path_def_id(cx, fun).and_then(|ctor_id| cx.tcx.parent(ctor_id));
if Some(id) == cx.tcx.lang_items().option_some_variant();
then {
let mut applicability = Applicability::MachineApplicable;
let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0][0]).peel_refs();
@ -42,7 +39,7 @@ pub(super) fn check(
if info.eq { "" } else { "!" },
snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability),
suggest,
snippet_with_applicability(cx, arg_char[0].span, "..", &mut applicability)),
snippet_with_applicability(cx, arg_char.span, "..", &mut applicability)),
applicability,
);

View file

@ -32,7 +32,7 @@ pub(super) fn check<'tcx>(
if info.eq { "" } else { "!" },
snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability),
suggest,
c),
c.escape_default()),
applicability,
);

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::is_qpath_def_path;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{match_def_path, path_def_id};
use if_chain::if_chain;
use rustc_ast::ast;
use rustc_errors::Applicability;
@ -93,12 +93,12 @@ fn is_min_or_max<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) -> Option<M
let ty_str = ty.to_string();
// `std::T::MAX` `std::T::MIN` constants
if let hir::ExprKind::Path(path) = &expr.kind {
if is_qpath_def_path(cx, path, expr.hir_id, &["core", &ty_str, "MAX"][..]) {
if let Some(id) = path_def_id(cx, expr) {
if match_def_path(cx, id, &["core", &ty_str, "MAX"]) {
return Some(MinMax::Max);
}
if is_qpath_def_path(cx, path, expr.hir_id, &["core", &ty_str, "MIN"][..]) {
if match_def_path(cx, id, &["core", &ty_str, "MIN"]) {
return Some(MinMax::Min);
}
}

View file

@ -566,17 +566,20 @@ declare_clippy_lint! {
///
/// ### Why is this bad?
/// Readability, this can be written more concisely as
/// `_.flat_map(_)`
/// `_.flat_map(_)` for `Iterator` or `_.and_then(_)` for `Option`
///
/// ### Example
/// ```rust
/// let vec = vec![vec![1]];
/// let opt = Some(5);
///
/// // Bad
/// vec.iter().map(|x| x.iter()).flatten();
/// opt.map(|x| Some(x * 2)).flatten();
///
/// // Good
/// vec.iter().flat_map(|x| x.iter());
/// opt.and_then(|x| Some(x * 2));
/// ```
#[clippy::version = "1.31.0"]
pub MAP_FLATTEN,
@ -2399,10 +2402,17 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
("to_os_string" | "to_owned" | "to_path_buf" | "to_vec", []) => {
implicit_clone::check(cx, name, expr, recv);
},
("unwrap", []) => match method_call(recv) {
Some(("get", [recv, get_arg], _)) => get_unwrap::check(cx, expr, recv, get_arg, false),
Some(("get_mut", [recv, get_arg], _)) => get_unwrap::check(cx, expr, recv, get_arg, true),
_ => unwrap_used::check(cx, expr, recv),
("unwrap", []) => {
match method_call(recv) {
Some(("get", [recv, get_arg], _)) => {
get_unwrap::check(cx, expr, recv, get_arg, false);
},
Some(("get_mut", [recv, get_arg], _)) => {
get_unwrap::check(cx, expr, recv, get_arg, true);
},
_ => {},
}
unwrap_used::check(cx, expr, recv);
},
("unwrap_or", [u_arg]) => match method_call(recv) {
Some((arith @ ("checked_add" | "checked_sub" | "checked_mul"), [lhs, rhs], _)) => {

View file

@ -1,11 +1,12 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{is_lang_ctor, single_segment_path};
use clippy_utils::{is_lang_ctor, path_def_id};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::LangItem::{OptionNone, OptionSome};
use rustc_lint::LateContext;
use rustc_middle::ty::DefIdTree;
use rustc_span::symbol::sym;
use super::OPTION_MAP_OR_NONE;
@ -76,13 +77,11 @@ pub(super) fn check<'tcx>(
if let hir::ExprKind::Closure(_, _, id, span, _) = map_arg.kind;
let arg_snippet = snippet(cx, span, "..");
let body = cx.tcx.hir().body(id);
if let Some((func, arg_char)) = reduce_unit_expression(cx, &body.value);
if arg_char.len() == 1;
if let hir::ExprKind::Path(ref qpath) = func.kind;
if let Some(segment) = single_segment_path(qpath);
if segment.ident.name == sym::Some;
if let Some((func, [arg_char])) = reduce_unit_expression(cx, &body.value);
if let Some(id) = path_def_id(cx, func).and_then(|ctor_id| cx.tcx.parent(ctor_id));
if Some(id) == cx.tcx.lang_items().option_some_variant();
then {
let func_snippet = snippet(cx, arg_char[0].span, "..");
let func_snippet = snippet(cx, arg_char.span, "..");
let msg = "called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling \
`map(..)` instead";
return span_lint_and_sugg(

View file

@ -1,5 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::differing_macro_contexts;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_copy;
use clippy_utils::ty::is_type_diagnostic_item;
@ -48,7 +47,7 @@ pub(super) fn check<'tcx>(
}
}
if differing_macro_contexts(unwrap_arg.span, map_span) {
if unwrap_arg.span.ctxt() != map_span.ctxt() {
return;
}

View file

@ -45,16 +45,16 @@ pub(super) fn check_manual_split_once(
IterUsageKind::Next | IterUsageKind::Second => {
let self_deref = {
let adjust = cx.typeck_results().expr_adjustments(self_arg);
if adjust.is_empty() {
if adjust.len() < 2 {
String::new()
} else if cx.typeck_results().expr_ty(self_arg).is_box()
|| adjust
.iter()
.any(|a| matches!(a.kind, Adjust::Deref(Some(_))) || a.target.is_box())
{
format!("&{}", "*".repeat(adjust.len() - 1))
format!("&{}", "*".repeat(adjust.len().saturating_sub(1)))
} else {
"*".repeat(adjust.len() - 2)
"*".repeat(adjust.len().saturating_sub(2))
}
};
if matches!(usage.kind, IterUsageKind::Next) {

View file

@ -33,9 +33,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<
} else if !found_mapping && !mutates_arg {
let in_ty = cx.typeck_results().node_type(body.params[0].hir_id);
match cx.typeck_results().expr_ty(&body.value).kind() {
ty::Adt(adt, subst)
if cx.tcx.is_diagnostic_item(sym::Option, adt.did) && in_ty == subst.type_at(0) =>
{
ty::Adt(adt, subst) if cx.tcx.is_diagnostic_item(sym::Option, adt.did) && in_ty == subst.type_at(0) => {
"filter"
},
_ => return,