Merge remote-tracking branch 'upstream/master' into rustup
This commit is contained in:
commit
1ced73e66a
204 changed files with 4209 additions and 2537 deletions
|
|
@ -167,14 +167,12 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name:
|
|||
} else {
|
||||
edits.extend(addr_of_edits);
|
||||
}
|
||||
edits.push((
|
||||
name_span,
|
||||
String::from(match name {
|
||||
"map" => "inspect",
|
||||
"map_err" => "inspect_err",
|
||||
_ => return,
|
||||
}),
|
||||
));
|
||||
let edit = match name {
|
||||
"map" => "inspect",
|
||||
"map_err" => "inspect_err",
|
||||
_ => return,
|
||||
};
|
||||
edits.push((name_span, edit.to_string()));
|
||||
edits.push((
|
||||
final_expr
|
||||
.span
|
||||
|
|
@ -187,9 +185,15 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name:
|
|||
} else {
|
||||
Applicability::MachineApplicable
|
||||
};
|
||||
span_lint_and_then(cx, MANUAL_INSPECT, name_span, "", |diag| {
|
||||
diag.multipart_suggestion("try", edits, app);
|
||||
});
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
MANUAL_INSPECT,
|
||||
name_span,
|
||||
format!("using `{name}` over `{edit}`"),
|
||||
|diag| {
|
||||
diag.multipart_suggestion("try", edits, app);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -628,12 +628,11 @@ declare_clippy_lint! {
|
|||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for usage of `_.and_then(|x| Some(y))`, `_.and_then(|x| Ok(y))` or
|
||||
/// `_.or_else(|x| Err(y))`.
|
||||
/// Checks for usage of `_.and_then(|x| Some(y))`, `_.and_then(|x| Ok(y))`
|
||||
/// or `_.or_else(|x| Err(y))`.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Readability, this can be written more concisely as
|
||||
/// `_.map(|x| y)` or `_.map_err(|x| y)`.
|
||||
/// This can be written more concisely as `_.map(|x| y)` or `_.map_err(|x| y)`.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```no_run
|
||||
|
|
@ -4121,7 +4120,7 @@ declare_clippy_lint! {
|
|||
/// ```no_run
|
||||
/// let x = Some(0).inspect(|x| println!("{x}"));
|
||||
/// ```
|
||||
#[clippy::version = "1.78.0"]
|
||||
#[clippy::version = "1.81.0"]
|
||||
pub MANUAL_INSPECT,
|
||||
complexity,
|
||||
"use of `map` returning the original item"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ use clippy_utils::ty::implements_trait;
|
|||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Closure, Expr, ExprKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QPath};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::{self, GenericArgKind};
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::GenericArgKind;
|
||||
use rustc_span::sym;
|
||||
use rustc_span::symbol::Ident;
|
||||
use std::iter;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
use super::implicit_clone::is_clone_like;
|
||||
use super::unnecessary_iter_cloned::{self, is_into_iter};
|
||||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
|
||||
use clippy_utils::source::{snippet, snippet_opt};
|
||||
use clippy_utils::ty::{
|
||||
get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item, peel_mid_ty_refs,
|
||||
};
|
||||
use clippy_utils::visitors::find_all_ret_expressions;
|
||||
use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty};
|
||||
use clippy_utils::{
|
||||
fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, match_def_path, paths, return_ty,
|
||||
};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
|
@ -52,6 +54,9 @@ pub fn check<'tcx>(
|
|||
if check_into_iter_call_arg(cx, expr, method_name, receiver, msrv) {
|
||||
return;
|
||||
}
|
||||
if check_string_from_utf8(cx, expr, receiver) {
|
||||
return;
|
||||
}
|
||||
check_other_call_arg(cx, expr, method_name, receiver);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -240,6 +245,65 @@ fn check_into_iter_call_arg(
|
|||
false
|
||||
}
|
||||
|
||||
/// Checks for `&String::from_utf8(bytes.{to_vec,to_owned,...}()).unwrap()` coercing to `&str`,
|
||||
/// which can be written as just `std::str::from_utf8(bytes).unwrap()`.
|
||||
fn check_string_from_utf8<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, receiver: &'tcx Expr<'tcx>) -> bool {
|
||||
if let Some((call, arg)) = skip_addr_of_ancestors(cx, expr)
|
||||
&& !arg.span.from_expansion()
|
||||
&& let ExprKind::Call(callee, _) = call.kind
|
||||
&& fn_def_id(cx, call).is_some_and(|did| match_def_path(cx, did, &paths::STRING_FROM_UTF8))
|
||||
&& let Some(unwrap_call) = get_parent_expr(cx, call)
|
||||
&& let ExprKind::MethodCall(unwrap_method_name, ..) = unwrap_call.kind
|
||||
&& matches!(unwrap_method_name.ident.name, sym::unwrap | sym::expect)
|
||||
&& let Some(ref_string) = get_parent_expr(cx, unwrap_call)
|
||||
&& let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, _) = ref_string.kind
|
||||
&& let adjusted_ty = cx.typeck_results().expr_ty_adjusted(ref_string)
|
||||
// `&...` creates a `&String`, so only actually lint if this coerces to a `&str`
|
||||
&& matches!(adjusted_ty.kind(), ty::Ref(_, ty, _) if ty.is_str())
|
||||
{
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
UNNECESSARY_TO_OWNED,
|
||||
ref_string.span,
|
||||
"allocating a new `String` only to create a temporary `&str` from it",
|
||||
|diag| {
|
||||
let arg_suggestion = format!(
|
||||
"{borrow}{recv_snippet}",
|
||||
recv_snippet = snippet(cx, receiver.span.source_callsite(), ".."),
|
||||
borrow = if cx.typeck_results().expr_ty(receiver).is_ref() {
|
||||
""
|
||||
} else {
|
||||
// If not already a reference, prefix with a borrow so that it can coerce to one
|
||||
"&"
|
||||
}
|
||||
);
|
||||
|
||||
diag.multipart_suggestion(
|
||||
"convert from `&[u8]` to `&str` directly",
|
||||
vec![
|
||||
// `&String::from_utf8(bytes.to_vec()).unwrap()`
|
||||
// ^^^^^^^^^^^^^^^^^
|
||||
(callee.span, "core::str::from_utf8".into()),
|
||||
// `&String::from_utf8(bytes.to_vec()).unwrap()`
|
||||
// ^
|
||||
(
|
||||
ref_string.span.shrink_to_lo().to(unwrap_call.span.shrink_to_lo()),
|
||||
String::new(),
|
||||
),
|
||||
// `&String::from_utf8(bytes.to_vec()).unwrap()`
|
||||
// ^^^^^^^^^^^^^^
|
||||
(arg.span, arg_suggestion),
|
||||
],
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
},
|
||||
);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks whether `expr` is an argument in an `into_iter` call and, if so, determines whether its
|
||||
/// call of a `to_owned`-like function is unnecessary.
|
||||
fn check_split_call_arg(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol, receiver: &Expr<'_>) -> bool {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::ty::{is_never_like, is_type_diagnostic_item};
|
||||
use clippy_utils::{is_in_cfg_test, is_in_test_function, is_lint_allowed};
|
||||
use clippy_utils::{is_in_test, is_lint_allowed};
|
||||
use rustc_hir::Expr;
|
||||
use rustc_lint::{LateContext, Lint};
|
||||
use rustc_middle::ty;
|
||||
|
|
@ -61,7 +61,7 @@ pub(super) fn check(
|
|||
|
||||
let method_suffix = if is_err { "_err" } else { "" };
|
||||
|
||||
if allow_unwrap_in_tests && (is_in_test_function(cx.tcx, expr.hir_id) || is_in_cfg_test(cx.tcx, expr.hir_id)) {
|
||||
if allow_unwrap_in_tests && is_in_test(cx.tcx, expr.hir_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue