Auto merge of #13540 - GnomedDev:create-dir-single-arg, r=y21
Check MethodCall/Call arg count earlier or at all This gets rid of a bunch of possible panic spots, as well as bailing out earlier for optimisation reasons. I started doing this because I saw that a significant amount of time was being spent in the `create_dir` restriction lint when running clippy with `perf`, but this also helps with robustness. changelog: none
This commit is contained in:
commit
236751d093
@ -47,7 +47,7 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
// And the call is that of a `Box` method
|
||||
&& path_def_id(cx, ty).map_or(false, |id| Some(id) == cx.tcx.lang_items().owned_box())
|
||||
// And the single argument to the call is another function call
|
||||
// This is the `T::default()` of `Box::new(T::default())`
|
||||
// This is the `T::default()` (or default equivalent) of `Box::new(T::default())`
|
||||
&& let ExprKind::Call(arg_path, _) = arg.kind
|
||||
// And we are not in a foreign crate's macro
|
||||
&& !in_external_macro(cx.sess(), expr.span)
|
||||
|
@ -19,7 +19,7 @@ pub(super) fn check(
|
||||
if msrv.meets(msrvs::UNSIGNED_ABS)
|
||||
&& let ty::Int(from) = cast_from.kind()
|
||||
&& let ty::Uint(to) = cast_to.kind()
|
||||
&& let ExprKind::MethodCall(method_path, receiver, ..) = cast_expr.kind
|
||||
&& let ExprKind::MethodCall(method_path, receiver, [], _) = cast_expr.kind
|
||||
&& method_path.ident.name.as_str() == "abs"
|
||||
{
|
||||
let span = if from.bit_width() == to.bit_width() {
|
||||
|
@ -19,7 +19,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
cx.typeck_results().expr_ty(expr),
|
||||
);
|
||||
lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
|
||||
} else if let ExprKind::MethodCall(method_path, self_arg, ..) = &expr.kind {
|
||||
} else if let ExprKind::MethodCall(method_path, self_arg, [], _) = &expr.kind {
|
||||
if method_path.ident.name == sym!(cast)
|
||||
&& let Some(generic_args) = method_path.args
|
||||
&& let [GenericArg::Type(cast_to)] = generic_args.args
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
impl LateLintPass<'_> for CreateDir {
|
||||
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
if let ExprKind::Call(func, [arg, ..]) = expr.kind
|
||||
if let ExprKind::Call(func, [arg]) = expr.kind
|
||||
&& let ExprKind::Path(ref path) = func.kind
|
||||
&& let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id()
|
||||
&& cx.tcx.is_diagnostic_item(sym::fs_create_dir, def_id)
|
||||
|
@ -83,7 +83,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if !expr.span.from_expansion()
|
||||
// Avoid cases already linted by `field_reassign_with_default`
|
||||
&& !self.reassigned_linted.contains(&expr.span)
|
||||
&& let ExprKind::Call(path, ..) = expr.kind
|
||||
&& let ExprKind::Call(path, []) = expr.kind
|
||||
&& !in_automatically_derived(cx.tcx, expr.hir_id)
|
||||
&& let ExprKind::Path(ref qpath) = path.kind
|
||||
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
|
||||
@ -253,7 +253,7 @@ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &Block<'tcx>) {
|
||||
|
||||
/// Checks if the given expression is the `default` method belonging to the `Default` trait.
|
||||
fn is_expr_default<'tcx>(expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> bool {
|
||||
if let ExprKind::Call(fn_expr, _) = &expr.kind
|
||||
if let ExprKind::Call(fn_expr, []) = &expr.kind
|
||||
&& let ExprKind::Path(qpath) = &fn_expr.kind
|
||||
&& let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id)
|
||||
{
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for Exit {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
|
||||
if let ExprKind::Call(path_expr, _args) = e.kind
|
||||
if let ExprKind::Call(path_expr, [_]) = e.kind
|
||||
&& let ExprKind::Path(ref path) = path_expr.kind
|
||||
&& let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id()
|
||||
&& cx.tcx.is_diagnostic_item(sym::process_exit, def_id)
|
||||
|
@ -57,7 +57,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
&& unwrap_fun.ident.name == sym::unwrap
|
||||
// match call to write_fmt
|
||||
&& let ExprKind::MethodCall(write_fun, write_recv, [write_arg], _) = *look_in_block(cx, &write_call.kind)
|
||||
&& let ExprKind::Call(write_recv_path, _) = write_recv.kind
|
||||
&& let ExprKind::Call(write_recv_path, []) = write_recv.kind
|
||||
&& write_fun.ident.name == sym!(write_fmt)
|
||||
&& let Some(def_id) = path_def_id(cx, write_recv_path)
|
||||
{
|
||||
|
@ -436,12 +436,12 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
lhs,
|
||||
rhs,
|
||||
) = expr.kind
|
||||
&& let ExprKind::MethodCall(path, self_arg, [], _) = &lhs.kind
|
||||
&& path.ident.name.as_str() == "exp"
|
||||
&& cx.typeck_results().expr_ty(lhs).is_floating_point()
|
||||
&& let Some(value) = ConstEvalCtxt::new(cx).eval(rhs)
|
||||
&& (F32(1.0) == value || F64(1.0) == value)
|
||||
&& let ExprKind::MethodCall(path, self_arg, ..) = &lhs.kind
|
||||
&& cx.typeck_results().expr_ty(self_arg).is_floating_point()
|
||||
&& path.ident.name.as_str() == "exp"
|
||||
{
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
|
@ -151,7 +151,7 @@ struct FormatImplExpr<'a, 'tcx> {
|
||||
impl FormatImplExpr<'_, '_> {
|
||||
fn check_to_string_in_display(&self) {
|
||||
if self.format_trait_impl.name == sym::Display
|
||||
&& let ExprKind::MethodCall(path, self_arg, ..) = self.expr.kind
|
||||
&& let ExprKind::MethodCall(path, self_arg, [], _) = self.expr.kind
|
||||
// Get the hir_id of the object we are calling the method on
|
||||
// Is the method to_string() ?
|
||||
&& path.ident.name == sym::to_string
|
||||
|
@ -82,7 +82,7 @@ fn mutex_lock_call<'tcx>(
|
||||
expr: &'tcx Expr<'_>,
|
||||
op_mutex: Option<&'tcx Expr<'_>>,
|
||||
) -> ControlFlow<&'tcx Expr<'tcx>> {
|
||||
if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind
|
||||
if let ExprKind::MethodCall(path, self_arg, [], _) = &expr.kind
|
||||
&& path.ident.as_str() == "lock"
|
||||
&& let ty = cx.typeck_results().expr_ty(self_arg).peel_refs()
|
||||
&& is_type_diagnostic_item(cx, ty, sym::Mutex)
|
||||
|
@ -57,7 +57,7 @@ pub fn new(conf: &'static Conf) -> Self {
|
||||
impl<'tcx> LateLintPass<'tcx> for LargeFuture {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||
if let ExprKind::Match(scrutinee, _, MatchSource::AwaitDesugar) = expr.kind
|
||||
&& let ExprKind::Call(func, [arg, ..]) = scrutinee.kind
|
||||
&& let ExprKind::Call(func, [arg]) = scrutinee.kind
|
||||
&& let ExprKind::Path(QPath::LangItem(LangItem::IntoFutureIntoFuture, ..)) = func.kind
|
||||
&& !expr.span.from_expansion()
|
||||
&& let ty = cx.typeck_results().expr_ty(arg)
|
||||
|
@ -517,7 +517,7 @@ fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>
|
||||
return;
|
||||
}
|
||||
|
||||
if let (&ExprKind::MethodCall(method_path, receiver, args, _), ExprKind::Lit(lit)) = (&method.kind, &lit.kind) {
|
||||
if let (&ExprKind::MethodCall(method_path, receiver, [], _), ExprKind::Lit(lit)) = (&method.kind, &lit.kind) {
|
||||
// check if we are in an is_empty() method
|
||||
if let Some(name) = get_item_name(cx, method) {
|
||||
if name.as_str() == "is_empty" {
|
||||
@ -525,29 +525,17 @@ fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>
|
||||
}
|
||||
}
|
||||
|
||||
check_len(
|
||||
cx,
|
||||
span,
|
||||
method_path.ident.name,
|
||||
receiver,
|
||||
args,
|
||||
&lit.node,
|
||||
op,
|
||||
compare_to,
|
||||
);
|
||||
check_len(cx, span, method_path.ident.name, receiver, &lit.node, op, compare_to);
|
||||
} else {
|
||||
check_empty_expr(cx, span, method, lit, op);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(flip1995): Figure out how to reduce the number of arguments
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn check_len(
|
||||
cx: &LateContext<'_>,
|
||||
span: Span,
|
||||
method_name: Symbol,
|
||||
receiver: &Expr<'_>,
|
||||
args: &[Expr<'_>],
|
||||
lit: &LitKind,
|
||||
op: &str,
|
||||
compare_to: u32,
|
||||
@ -558,7 +546,7 @@ fn check_len(
|
||||
return;
|
||||
}
|
||||
|
||||
if method_name == sym::len && args.is_empty() && has_is_empty(cx, receiver) {
|
||||
if method_name == sym::len && has_is_empty(cx, receiver) {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
|
@ -47,8 +47,9 @@ fn report_lint(cx: &LateContext<'_>, pop_span: Span, pop_stmt_kind: PopStmt<'_>,
|
||||
);
|
||||
}
|
||||
|
||||
fn match_method_call(cx: &LateContext<'_>, expr: &Expr<'_>, method: Symbol) -> bool {
|
||||
if let ExprKind::MethodCall(..) = expr.kind
|
||||
fn match_method_call<const ARGS_COUNT: usize>(cx: &LateContext<'_>, expr: &Expr<'_>, method: Symbol) -> bool {
|
||||
if let ExprKind::MethodCall(_, _, args, _) = expr.kind
|
||||
&& args.len() == ARGS_COUNT
|
||||
&& let Some(id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
|
||||
{
|
||||
cx.tcx.is_diagnostic_item(method, id)
|
||||
@ -58,9 +59,9 @@ fn match_method_call(cx: &LateContext<'_>, expr: &Expr<'_>, method: Symbol) -> b
|
||||
}
|
||||
|
||||
fn is_vec_pop_unwrap(cx: &LateContext<'_>, expr: &Expr<'_>, is_empty_recv: &Expr<'_>) -> bool {
|
||||
if (match_method_call(cx, expr, sym::option_unwrap) || match_method_call(cx, expr, sym::option_expect))
|
||||
if (match_method_call::<0>(cx, expr, sym::option_unwrap) || match_method_call::<1>(cx, expr, sym::option_expect))
|
||||
&& let ExprKind::MethodCall(_, unwrap_recv, ..) = expr.kind
|
||||
&& match_method_call(cx, unwrap_recv, sym::vec_pop)
|
||||
&& match_method_call::<0>(cx, unwrap_recv, sym::vec_pop)
|
||||
&& let ExprKind::MethodCall(_, pop_recv, ..) = unwrap_recv.kind
|
||||
{
|
||||
// make sure they're the same `Vec`
|
||||
@ -96,7 +97,7 @@ fn check_call_arguments(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &E
|
||||
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, full_cond: &'tcx Expr<'_>, body: &'tcx Expr<'_>, loop_span: Span) {
|
||||
if let ExprKind::Unary(UnOp::Not, cond) = full_cond.kind
|
||||
&& let ExprKind::MethodCall(_, is_empty_recv, _, _) = cond.kind
|
||||
&& match_method_call(cx, cond, sym::vec_is_empty)
|
||||
&& match_method_call::<0>(cx, cond, sym::vec_is_empty)
|
||||
&& let ExprKind::Block(body, _) = body.kind
|
||||
&& let Some(stmt) = body.stmts.first()
|
||||
{
|
||||
|
@ -172,10 +172,8 @@ fn get_vec_push<'tcx>(
|
||||
stmt: &'tcx Stmt<'_>,
|
||||
) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, SyntaxContext)> {
|
||||
if let StmtKind::Semi(semi_stmt) = &stmt.kind
|
||||
// Extract method being called
|
||||
&& let ExprKind::MethodCall(path, self_expr, args, _) = &semi_stmt.kind
|
||||
// Figure out the parameters for the method call
|
||||
&& let Some(pushed_item) = args.first()
|
||||
// Extract method being called and figure out the parameters for the method call
|
||||
&& let ExprKind::MethodCall(path, self_expr, [pushed_item], _) = &semi_stmt.kind
|
||||
// Check that the method being called is push() on a Vec
|
||||
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_expr), sym::Vec)
|
||||
&& path.ident.name.as_str() == "push"
|
||||
|
@ -42,7 +42,7 @@ fn check_expr_post(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let ExprKind::Call(func, _) = &expr.kind
|
||||
if let ExprKind::Call(func, []) = &expr.kind
|
||||
&& let ExprKind::Path(QPath::Resolved(_, path)) = &func.kind
|
||||
&& let Some(def_id) = path.res.opt_def_id()
|
||||
&& is_entrypoint_fn(cx, def_id)
|
||||
|
@ -95,7 +95,7 @@ fn get_one_size_of_ty<'tcx>(
|
||||
}
|
||||
|
||||
fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<(&'tcx rustc_hir::Ty<'tcx>, Ty<'tcx>)> {
|
||||
if let ExprKind::Call(count_func, _func_args) = expr.kind
|
||||
if let ExprKind::Call(count_func, []) = expr.kind
|
||||
&& let ExprKind::Path(ref count_func_qpath) = count_func.kind
|
||||
&& let QPath::Resolved(_, count_func_path) = count_func_qpath
|
||||
&& let Some(segment_zero) = count_func_path.segments.first()
|
||||
|
@ -41,7 +41,7 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
&& bin_op.node == BinOpKind::Eq
|
||||
{
|
||||
// a.count_ones() == 1
|
||||
if let ExprKind::MethodCall(method_name, reciever, _, _) = left.kind
|
||||
if let ExprKind::MethodCall(method_name, reciever, [], _) = left.kind
|
||||
&& method_name.ident.as_str() == "count_ones"
|
||||
&& let &Uint(_) = cx.typeck_results().expr_ty(reciever).kind()
|
||||
&& check_lit(right, 1)
|
||||
@ -50,7 +50,7 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
}
|
||||
|
||||
// 1 == a.count_ones()
|
||||
if let ExprKind::MethodCall(method_name, reciever, _, _) = right.kind
|
||||
if let ExprKind::MethodCall(method_name, reciever, [], _) = right.kind
|
||||
&& method_name.ident.as_str() == "count_ones"
|
||||
&& let &Uint(_) = cx.typeck_results().expr_ty(reciever).kind()
|
||||
&& check_lit(left, 1)
|
||||
|
@ -83,12 +83,12 @@ fn simplify_half<'tcx>(
|
||||
) -> Option<&'tcx Expr<'tcx>> {
|
||||
if !expr1.span.from_expansion()
|
||||
// expr1 is `[T1].len()`?
|
||||
&& let ExprKind::MethodCall(method_path, receiver, _, _) = expr1.kind
|
||||
&& let ExprKind::MethodCall(method_path, receiver, [], _) = expr1.kind
|
||||
&& method_path.ident.name == sym::len
|
||||
&& let receiver_ty = cx.typeck_results().expr_ty(receiver)
|
||||
&& let ty::Slice(ty1) = receiver_ty.peel_refs().kind()
|
||||
// expr2 is `size_of::<T2>()`?
|
||||
&& let ExprKind::Call(func, _) = expr2.kind
|
||||
&& let ExprKind::Call(func, []) = expr2.kind
|
||||
&& let ExprKind::Path(ref func_qpath) = func.kind
|
||||
&& let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id()
|
||||
&& cx.tcx.is_diagnostic_item(sym::mem_size_of, def_id)
|
||||
|
@ -52,8 +52,8 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
}
|
||||
|
||||
match expr.kind {
|
||||
ExprKind::Call(func, args) => {
|
||||
parse_call(cx, expr.span, func, args);
|
||||
ExprKind::Call(func, [arg]) => {
|
||||
parse_call(cx, expr.span, func, arg);
|
||||
},
|
||||
ExprKind::MethodCall(path_segment, receiver, ..) => {
|
||||
parse_method_call(cx, expr.span, path_segment, receiver);
|
||||
@ -93,20 +93,15 @@ fn parse_method_call(cx: &LateContext<'_>, span: Span, path_segment: &PathSegmen
|
||||
let method_arg_kind = &receiver.kind;
|
||||
if ["to_string", "to_owned", "into"].contains(&ident) && is_expr_kind_empty_str(method_arg_kind) {
|
||||
warn_then_suggest(cx, span);
|
||||
} else if let ExprKind::Call(func, args) = method_arg_kind {
|
||||
} else if let ExprKind::Call(func, [arg]) = method_arg_kind {
|
||||
// If our first argument is a function call itself, it could be an `unwrap`-like function.
|
||||
// E.g. String::try_from("hello").unwrap(), TryFrom::try_from("").expect("hello"), etc.
|
||||
parse_call(cx, span, func, args);
|
||||
parse_call(cx, span, func, arg);
|
||||
}
|
||||
}
|
||||
|
||||
/// Tries to parse an expression as a function call, emitting the warning if necessary.
|
||||
fn parse_call(cx: &LateContext<'_>, span: Span, func: &Expr<'_>, args: &[Expr<'_>]) {
|
||||
if args.len() != 1 {
|
||||
return;
|
||||
}
|
||||
|
||||
let arg_kind = &args[0].kind;
|
||||
fn parse_call(cx: &LateContext<'_>, span: Span, func: &Expr<'_>, arg: &Expr<'_>) {
|
||||
if let ExprKind::Path(qpath) = &func.kind {
|
||||
// String::from(...) or String::try_from(...)
|
||||
if let QPath::TypeRelative(ty, path_seg) = qpath
|
||||
@ -115,13 +110,13 @@ fn parse_call(cx: &LateContext<'_>, span: Span, func: &Expr<'_>, args: &[Expr<'_
|
||||
&& let QPath::Resolved(_, path) = qpath
|
||||
&& let [path_seg] = path.segments
|
||||
&& path_seg.ident.name == sym::String
|
||||
&& is_expr_kind_empty_str(arg_kind)
|
||||
&& is_expr_kind_empty_str(&arg.kind)
|
||||
{
|
||||
warn_then_suggest(cx, span);
|
||||
} else if let QPath::Resolved(_, path) = qpath {
|
||||
// From::from(...) or TryFrom::try_from(...)
|
||||
if let [path_seg1, path_seg2] = path.segments
|
||||
&& is_expr_kind_empty_str(arg_kind)
|
||||
&& is_expr_kind_empty_str(&arg.kind)
|
||||
&& ((path_seg1.ident.name == sym::From && path_seg2.ident.name == sym::from)
|
||||
|| (path_seg1.ident.name == sym::TryFrom && path_seg2.ident.name == sym::try_from))
|
||||
{
|
||||
|
@ -210,7 +210,7 @@ fn find_method_sugg_for_if_let<'tcx>(
|
||||
|
||||
// check that `while_let_on_iterator` lint does not trigger
|
||||
if keyword == "while"
|
||||
&& let ExprKind::MethodCall(method_path, ..) = let_expr.kind
|
||||
&& let ExprKind::MethodCall(method_path, _, [], _) = let_expr.kind
|
||||
&& method_path.ident.name == sym::next
|
||||
&& is_trait_method(cx, let_expr, sym::Iterator)
|
||||
{
|
||||
|
@ -21,10 +21,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine
|
||||
// #[allow(unreachable_code)]
|
||||
// val,
|
||||
// };
|
||||
if let ExprKind::Call(match_fun, [try_arg, ..]) = scrutinee.kind
|
||||
if let ExprKind::Call(match_fun, [try_arg]) = scrutinee.kind
|
||||
&& let ExprKind::Path(ref match_fun_path) = match_fun.kind
|
||||
&& matches!(match_fun_path, QPath::LangItem(LangItem::TryTraitBranch, ..))
|
||||
&& let ExprKind::Call(err_fun, [err_arg, ..]) = try_arg.kind
|
||||
&& let ExprKind::Call(err_fun, [err_arg]) = try_arg.kind
|
||||
&& is_res_lang_ctor(cx, path_res(cx, err_fun), ResultErr)
|
||||
&& let Some(return_ty) = find_return_type(cx, &expr.kind)
|
||||
{
|
||||
|
@ -58,7 +58,7 @@ pub(super) fn check(
|
||||
return;
|
||||
},
|
||||
// ? is a Call, makes sure not to rec *x?, but rather (*x)?
|
||||
ExprKind::Call(hir_callee, _) => matches!(
|
||||
ExprKind::Call(hir_callee, [_]) => matches!(
|
||||
hir_callee.kind,
|
||||
ExprKind::Path(QPath::LangItem(rustc_hir::LangItem::TryTraitBranch, ..))
|
||||
),
|
||||
|
@ -106,9 +106,9 @@ fn pat_is_recv(ident: Ident, param: &hir::Pat<'_>) -> bool {
|
||||
|
||||
fn parent_is_map(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
|
||||
if let Some(expr) = get_parent_expr(cx, expr)
|
||||
&& is_trait_method(cx, expr, sym::Iterator)
|
||||
&& let ExprKind::MethodCall(path, _, _, _) = expr.kind
|
||||
&& let ExprKind::MethodCall(path, _, [_], _) = expr.kind
|
||||
&& path.ident.name == sym::map
|
||||
&& is_trait_method(cx, expr, sym::Iterator)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, func: &Expr<'_>, args
|
||||
|
||||
/// Checks `CStr::from_ptr(b"foo\0".as_ptr().cast())`
|
||||
fn check_from_ptr(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>) {
|
||||
if let ExprKind::MethodCall(method, lit, ..) = peel_ptr_cast(arg).kind
|
||||
if let ExprKind::MethodCall(method, lit, [], _) = peel_ptr_cast(arg).kind
|
||||
&& method.ident.name == sym::as_ptr
|
||||
&& !lit.span.from_expansion()
|
||||
&& let ExprKind::Lit(lit) = lit.kind
|
||||
|
@ -68,8 +68,7 @@ enum MinMax {
|
||||
|
||||
fn is_min_or_max(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<MinMax> {
|
||||
// `T::max_value()` `T::min_value()` inherent methods
|
||||
if let hir::ExprKind::Call(func, args) = &expr.kind
|
||||
&& args.is_empty()
|
||||
if let hir::ExprKind::Call(func, []) = &expr.kind
|
||||
&& let hir::ExprKind::Path(hir::QPath::TypeRelative(_, segment)) = &func.kind
|
||||
{
|
||||
match segment.ident.as_str() {
|
||||
|
@ -86,9 +86,8 @@ pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_
|
||||
}
|
||||
}
|
||||
},
|
||||
hir::ExprKind::Call(call, args) => {
|
||||
hir::ExprKind::Call(call, [arg]) => {
|
||||
if let hir::ExprKind::Path(qpath) = call.kind
|
||||
&& let [arg] = args
|
||||
&& ident_eq(name, arg)
|
||||
{
|
||||
handle_path(cx, call, &qpath, e, recv);
|
||||
|
@ -321,7 +321,10 @@ fn visit_block(&mut self, block: &'tcx Block<'tcx>) {
|
||||
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
|
||||
// Check function calls on our collection
|
||||
if let ExprKind::MethodCall(method_name, recv, args, _) = &expr.kind {
|
||||
if method_name.ident.name == sym!(collect) && is_trait_method(self.cx, expr, sym::Iterator) {
|
||||
if args.is_empty()
|
||||
&& method_name.ident.name == sym!(collect)
|
||||
&& is_trait_method(self.cx, expr, sym::Iterator)
|
||||
{
|
||||
self.current_mutably_captured_ids = get_captured_ids(self.cx, self.cx.typeck_results().expr_ty(recv));
|
||||
self.visit_expr(recv);
|
||||
return;
|
||||
|
@ -259,7 +259,7 @@ fn closure_body_returns_empty_to_string(cx: &LateContext<'_>, e: &hir::Expr<'_>)
|
||||
|
||||
if body.params.is_empty()
|
||||
&& let hir::Expr { kind, .. } = &body.value
|
||||
&& let hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, self_arg, _, _) = kind
|
||||
&& let hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, self_arg, [], _) = kind
|
||||
&& ident.name == sym::to_string
|
||||
&& let hir::Expr { kind, .. } = self_arg
|
||||
&& let hir::ExprKind::Lit(lit) = kind
|
||||
|
@ -43,7 +43,8 @@ pub fn check(cx: &LateContext<'_>, call: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<
|
||||
for_each_local_use_after_expr(cx, local_id, call.hir_id, |expr| {
|
||||
if let Some(parent) = get_parent_expr(cx, expr) {
|
||||
let data = if let ExprKind::MethodCall(segment, recv, args, span) = parent.kind {
|
||||
if segment.ident.name == sym!(parse)
|
||||
if args.is_empty()
|
||||
&& segment.ident.name == sym!(parse)
|
||||
&& let parse_result_ty = cx.typeck_results().expr_ty(parent)
|
||||
&& is_type_diagnostic_item(cx, parse_result_ty, sym::Result)
|
||||
&& let ty::Adt(_, substs) = parse_result_ty.kind()
|
||||
|
@ -10,7 +10,7 @@
|
||||
use rustc_span::sym;
|
||||
|
||||
fn is_unwrap_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
if let ExprKind::MethodCall(path, receiver, ..) = expr.kind
|
||||
if let ExprKind::MethodCall(path, receiver, [], _) = expr.kind
|
||||
&& path.ident.name == sym::unwrap
|
||||
{
|
||||
is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(receiver).peel_refs(), sym::Result)
|
||||
|
@ -34,14 +34,13 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'
|
||||
}
|
||||
|
||||
fn arg_is_seek_from_current<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
|
||||
if let ExprKind::Call(f, args) = expr.kind
|
||||
if let ExprKind::Call(f, [arg]) = expr.kind
|
||||
&& let ExprKind::Path(ref path) = f.kind
|
||||
&& let Some(ctor_call_id) = cx.qpath_res(path, f.hir_id).opt_def_id()
|
||||
&& is_enum_variant_ctor(cx, sym::SeekFrom, sym!(Current), ctor_call_id)
|
||||
{
|
||||
// check if argument of `SeekFrom::Current` is `0`
|
||||
if args.len() == 1
|
||||
&& let ExprKind::Lit(lit) = args[0].kind
|
||||
if let ExprKind::Lit(lit) = arg.kind
|
||||
&& let LitKind::Int(Pu128(0), LitIntType::Unsuffixed) = lit.node
|
||||
{
|
||||
return true;
|
||||
|
@ -26,12 +26,11 @@ pub(super) fn check<'tcx>(
|
||||
|
||||
if let Some(seek_trait_id) = cx.tcx.get_diagnostic_item(sym::IoSeek)
|
||||
&& implements_trait(cx, ty, seek_trait_id, &[])
|
||||
&& let ExprKind::Call(func, args1) = arg.kind
|
||||
&& let ExprKind::Call(func, [arg]) = arg.kind
|
||||
&& let ExprKind::Path(ref path) = func.kind
|
||||
&& let Some(ctor_call_id) = cx.qpath_res(path, func.hir_id).opt_def_id()
|
||||
&& is_enum_variant_ctor(cx, sym::SeekFrom, sym!(Start), ctor_call_id)
|
||||
&& args1.len() == 1
|
||||
&& let ExprKind::Lit(lit) = args1[0].kind
|
||||
&& let ExprKind::Lit(lit) = arg.kind
|
||||
&& let LitKind::Int(Pu128(0), LitIntType::Unsuffixed) = lit.node
|
||||
{
|
||||
let method_call_span = expr.span.with_lo(name_span.lo());
|
||||
|
@ -27,7 +27,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::
|
||||
}
|
||||
|
||||
if let ExprKind::AddrOf(BorrowKind::Ref, _, arg) = &args[1].kind
|
||||
&& let ExprKind::MethodCall(path_segment, method_arg, _, _) = &arg.kind
|
||||
&& let ExprKind::MethodCall(path_segment, method_arg, [], _) = &arg.kind
|
||||
&& path_segment.ident.name == rustc_span::sym::to_string
|
||||
&& (is_ref_char(cx, method_arg) || is_char(cx, method_arg))
|
||||
{
|
||||
|
@ -26,7 +26,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::
|
||||
}
|
||||
|
||||
if let ExprKind::AddrOf(BorrowKind::Ref, _, arg) = &args[0].kind
|
||||
&& let ExprKind::MethodCall(path_segment, method_arg, _, _) = &arg.kind
|
||||
&& let ExprKind::MethodCall(path_segment, method_arg, [], _) = &arg.kind
|
||||
&& path_segment.ident.name == rustc_span::sym::to_string
|
||||
&& (is_ref_char(cx, method_arg) || is_char(cx, method_arg))
|
||||
{
|
||||
|
@ -333,7 +333,7 @@ fn parse_iter_usage<'tcx>(
|
||||
kind: ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, ..)),
|
||||
..
|
||||
},
|
||||
_,
|
||||
[_],
|
||||
) => {
|
||||
let parent_span = e.span.parent_callsite().unwrap();
|
||||
if parent_span.ctxt() == ctxt {
|
||||
|
@ -9,8 +9,7 @@
|
||||
|
||||
/// lint for `MaybeUninit::uninit().assume_init()` (we already have the latter)
|
||||
pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) {
|
||||
if let hir::ExprKind::Call(callee, args) = recv.kind
|
||||
&& args.is_empty()
|
||||
if let hir::ExprKind::Call(callee, []) = recv.kind
|
||||
&& is_path_diagnostic_item(cx, callee, sym::maybe_uninit_uninit)
|
||||
&& !is_uninit_value_valid_for_ty(cx, cx.typeck_results().expr_ty_adjusted(expr))
|
||||
{
|
||||
|
@ -86,12 +86,11 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str,
|
||||
// changing the type, then we can move forward.
|
||||
&& rcv_ty.peel_refs() == res_ty.peel_refs()
|
||||
&& let Some(parent) = get_parent_expr(cx, expr)
|
||||
&& let hir::ExprKind::MethodCall(segment, _, args, _) = parent.kind
|
||||
// Check that it only has one argument.
|
||||
&& let hir::ExprKind::MethodCall(segment, _, [arg], _) = parent.kind
|
||||
&& segment.ident.span != expr.span
|
||||
// We check that the called method name is `map`.
|
||||
&& segment.ident.name == sym::map
|
||||
// And that it only has one argument.
|
||||
&& let [arg] = args
|
||||
&& is_calling_clone(cx, arg)
|
||||
// And that we are not recommending recv.clone() over Arc::clone() or similar
|
||||
&& !should_call_clone_as_function(cx, rcv_ty)
|
||||
|
@ -139,7 +139,7 @@ fn assert_len_expr<'hir>(
|
||||
&& let ExprKind::Binary(bin_op, left, right) = &condition.kind
|
||||
|
||||
&& let Some((cmp, asserted_len, slice_len)) = len_comparison(*bin_op, left, right)
|
||||
&& let ExprKind::MethodCall(method, recv, ..) = &slice_len.kind
|
||||
&& let ExprKind::MethodCall(method, recv, [], _) = &slice_len.kind
|
||||
&& cx.typeck_results().expr_ty_adjusted(recv).peel_refs().is_slice()
|
||||
&& method.ident.name == sym::len
|
||||
|
||||
|
@ -47,7 +47,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
|
||||
if let ExprKind::Path(ref path) = fn_expr.kind {
|
||||
check_arguments(
|
||||
cx,
|
||||
arguments.iter().collect(),
|
||||
&mut arguments.iter(),
|
||||
cx.typeck_results().expr_ty(fn_expr),
|
||||
&rustc_hir_pretty::qpath_to_string(&cx.tcx, path),
|
||||
"function",
|
||||
@ -60,7 +60,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
|
||||
let method_type = cx.tcx.type_of(def_id).instantiate(cx.tcx, args);
|
||||
check_arguments(
|
||||
cx,
|
||||
iter::once(receiver).chain(arguments.iter()).collect(),
|
||||
&mut iter::once(receiver).chain(arguments.iter()),
|
||||
method_type,
|
||||
path.ident.as_str(),
|
||||
"method",
|
||||
@ -73,7 +73,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
|
||||
|
||||
fn check_arguments<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
arguments: Vec<&Expr<'_>>,
|
||||
arguments: &mut dyn Iterator<Item = &'tcx Expr<'tcx>>,
|
||||
type_definition: Ty<'tcx>,
|
||||
name: &str,
|
||||
fn_kind: &str,
|
||||
|
@ -281,7 +281,7 @@ fn self_cmp_call<'tcx>(
|
||||
needs_fully_qualified: &mut bool,
|
||||
) -> bool {
|
||||
match cmp_expr.kind {
|
||||
ExprKind::Call(path, [_self, _other]) => path_res(cx, path)
|
||||
ExprKind::Call(path, [_, _]) => path_res(cx, path)
|
||||
.opt_def_id()
|
||||
.is_some_and(|def_id| cx.tcx.is_diagnostic_item(sym::ord_cmp_method, def_id)),
|
||||
ExprKind::MethodCall(_, _, [_other], ..) => {
|
||||
|
@ -71,7 +71,7 @@ fn check_non_zero_conversion(cx: &LateContext<'_>, expr: &Expr<'_>, applicabilit
|
||||
if let ExprKind::Call(func, [arg]) = expr.kind
|
||||
&& let ExprKind::Path(qpath) = &func.kind
|
||||
&& let Some(def_id) = cx.qpath_res(qpath, func.hir_id).opt_def_id()
|
||||
&& let ExprKind::MethodCall(rcv_path, receiver, _, _) = &arg.kind
|
||||
&& let ExprKind::MethodCall(rcv_path, receiver, [], _) = &arg.kind
|
||||
&& rcv_path.ident.name.as_str() == "get"
|
||||
{
|
||||
let fn_name = cx.tcx.item_name(def_id);
|
||||
|
@ -106,7 +106,7 @@ fn is_signum(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
return is_signum(cx, child_expr);
|
||||
}
|
||||
|
||||
if let ExprKind::MethodCall(method_name, self_arg, ..) = expr.kind
|
||||
if let ExprKind::MethodCall(method_name, self_arg, [], _) = expr.kind
|
||||
&& sym!(signum) == method_name.ident.name
|
||||
// Check that the receiver of the signum() is a float (expressions[0] is the receiver of
|
||||
// the method call)
|
||||
|
@ -91,7 +91,7 @@ fn expr_as_ptr_offset_call<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
expr: &'tcx Expr<'_>,
|
||||
) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Method)> {
|
||||
if let ExprKind::MethodCall(path_segment, arg_0, [arg_1, ..], _) = &expr.kind {
|
||||
if let ExprKind::MethodCall(path_segment, arg_0, [arg_1], _) = &expr.kind {
|
||||
if is_expr_ty_raw_ptr(cx, arg_0) {
|
||||
if path_segment.ident.name == sym::offset {
|
||||
return Some((arg_0, arg_1, Method::Offset));
|
||||
|
@ -206,12 +206,11 @@ fn expr_return_none_or_err(
|
||||
sym::Result => path_to_local(expr).is_some() && path_to_local(expr) == path_to_local(cond_expr),
|
||||
_ => false,
|
||||
},
|
||||
ExprKind::Call(call_expr, args_expr) => {
|
||||
ExprKind::Call(call_expr, [arg]) => {
|
||||
if smbl == sym::Result
|
||||
&& let ExprKind::Path(QPath::Resolved(_, path)) = &call_expr.kind
|
||||
&& let Some(segment) = path.segments.first()
|
||||
&& let Some(err_sym) = err_sym
|
||||
&& let Some(arg) = args_expr.first()
|
||||
&& let ExprKind::Path(QPath::Resolved(_, arg_path)) = &arg.kind
|
||||
&& let Some(PathSegment { ident, .. }) = arg_path.segments.first()
|
||||
{
|
||||
@ -241,7 +240,7 @@ fn expr_return_none_or_err(
|
||||
fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
|
||||
if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr)
|
||||
&& !is_else_clause(cx.tcx, expr)
|
||||
&& let ExprKind::MethodCall(segment, caller, ..) = &cond.kind
|
||||
&& let ExprKind::MethodCall(segment, caller, [], _) = &cond.kind
|
||||
&& let caller_ty = cx.typeck_results().expr_ty(caller)
|
||||
&& let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then)
|
||||
&& (is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block))
|
||||
@ -332,7 +331,7 @@ fn inside_try_block(&self) -> bool {
|
||||
|
||||
fn is_try_block(cx: &LateContext<'_>, bl: &Block<'_>) -> bool {
|
||||
if let Some(expr) = bl.expr
|
||||
&& let ExprKind::Call(callee, _) = expr.kind
|
||||
&& let ExprKind::Call(callee, [_]) = expr.kind
|
||||
{
|
||||
is_path_lang_item(cx, callee, LangItem::TryTraitFromOutput)
|
||||
} else {
|
||||
|
@ -357,7 +357,7 @@ fn check_final_expr<'tcx>(
|
||||
|
||||
let replacement = if let Some(inner_expr) = inner {
|
||||
// if desugar of `do yeet`, don't lint
|
||||
if let ExprKind::Call(path_expr, _) = inner_expr.kind
|
||||
if let ExprKind::Call(path_expr, [_]) = inner_expr.kind
|
||||
&& let ExprKind::Path(QPath::LangItem(LangItem::TryTraitFromYeet, ..)) = path_expr.kind
|
||||
{
|
||||
return;
|
||||
|
@ -421,11 +421,10 @@ fn dummy_stmt_expr<'any>(expr: &'any hir::Expr<'any>) -> hir::Stmt<'any> {
|
||||
}
|
||||
|
||||
fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Ident, lcx: &LateContext<'_>) -> bool {
|
||||
if let hir::ExprKind::Call(fun, args) = expr.kind
|
||||
if let hir::ExprKind::Call(fun, [first_arg]) = expr.kind
|
||||
&& let hir::ExprKind::Path(hir::QPath::Resolved(_, fun_path)) = &fun.kind
|
||||
&& let Res::Def(DefKind::Fn, did) = fun_path.res
|
||||
&& lcx.tcx.is_diagnostic_item(sym::mem_drop, did)
|
||||
&& let [first_arg, ..] = args
|
||||
{
|
||||
let has_ident = |local_expr: &hir::Expr<'_>| {
|
||||
if let hir::ExprKind::Path(hir::QPath::Resolved(_, arg_path)) = &local_expr.kind
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, inverted: bool) -> Option<Ty<'tcx>> {
|
||||
match expr.kind {
|
||||
ExprKind::Call(count_func, _func_args) => {
|
||||
ExprKind::Call(count_func, _) => {
|
||||
if !inverted
|
||||
&& let ExprKind::Path(ref count_func_qpath) = count_func.kind
|
||||
&& let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id()
|
||||
|
@ -152,7 +152,7 @@ fn as_vec_initializer<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Opt
|
||||
&& is_path_diagnostic_item(cx, func, sym::vec_with_capacity)
|
||||
{
|
||||
Some(InitializedSize::Initialized(len_expr))
|
||||
} else if matches!(expr.kind, ExprKind::Call(func, _) if is_path_diagnostic_item(cx, func, sym::vec_new)) {
|
||||
} else if matches!(expr.kind, ExprKind::Call(func, []) if is_path_diagnostic_item(cx, func, sym::vec_new)) {
|
||||
Some(InitializedSize::Uninitialized)
|
||||
} else {
|
||||
None
|
||||
@ -268,7 +268,7 @@ fn search_slow_resize_filling(&mut self, expr: &'tcx Expr<'tcx>) {
|
||||
|
||||
/// Returns `true` if give expression is `repeat(0).take(...)`
|
||||
fn is_repeat_take(&mut self, expr: &'tcx Expr<'tcx>) -> bool {
|
||||
if let ExprKind::MethodCall(take_path, recv, [len_arg, ..], _) = expr.kind
|
||||
if let ExprKind::MethodCall(take_path, recv, [len_arg], _) = expr.kind
|
||||
&& take_path.ident.name == sym!(take)
|
||||
// Check that take is applied to `repeat(0)`
|
||||
&& self.is_repeat_zero(recv)
|
||||
|
@ -253,18 +253,17 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
|
||||
use rustc_ast::LitKind;
|
||||
|
||||
if let ExprKind::Call(fun, args) = e.kind
|
||||
if let ExprKind::Call(fun, [bytes_arg]) = e.kind
|
||||
// Find std::str::converts::from_utf8
|
||||
&& is_path_diagnostic_item(cx, fun, sym::str_from_utf8)
|
||||
|
||||
// Find string::as_bytes
|
||||
&& let ExprKind::AddrOf(BorrowKind::Ref, _, args) = args[0].kind
|
||||
&& let ExprKind::AddrOf(BorrowKind::Ref, _, args) = bytes_arg.kind
|
||||
&& let ExprKind::Index(left, right, _) = args.kind
|
||||
&& let (method_names, expressions, _) = method_calls(left, 1)
|
||||
&& method_names.len() == 1
|
||||
&& method_names == [sym!(as_bytes)]
|
||||
&& expressions.len() == 1
|
||||
&& expressions[0].1.is_empty()
|
||||
&& method_names[0] == sym!(as_bytes)
|
||||
|
||||
// Check for slicer
|
||||
&& let ExprKind::Struct(QPath::LangItem(LangItem::Range, ..), _, _) = right.kind
|
||||
@ -393,7 +392,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind
|
||||
if let ExprKind::MethodCall(path, self_arg, [], _) = &expr.kind
|
||||
&& path.ident.name == sym::to_string
|
||||
&& let ty = cx.typeck_results().expr_ty(self_arg)
|
||||
&& let ty::Ref(_, ty, ..) = ty.kind()
|
||||
@ -449,7 +448,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind
|
||||
if let ExprKind::MethodCall(path, self_arg, [], _) = &expr.kind
|
||||
&& path.ident.name == sym::to_string
|
||||
&& let ty = cx.typeck_results().expr_ty(self_arg)
|
||||
&& is_type_lang_item(cx, ty, LangItem::String)
|
||||
|
@ -51,9 +51,8 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
|
||||
None
|
||||
}
|
||||
},
|
||||
hir::ExprKind::Call(to_digits_call, to_digit_args) => {
|
||||
if let [char_arg, radix_arg] = *to_digit_args
|
||||
&& let hir::ExprKind::Path(to_digits_path) = &to_digits_call.kind
|
||||
hir::ExprKind::Call(to_digits_call, [char_arg, radix_arg]) => {
|
||||
if let hir::ExprKind::Path(to_digits_path) = &to_digits_call.kind
|
||||
&& let to_digits_call_res = cx.qpath_res(to_digits_path, to_digits_call.hir_id)
|
||||
&& let Some(to_digits_def_id) = to_digits_call_res.opt_def_id()
|
||||
&& match_def_path(cx, to_digits_def_id, &[
|
||||
|
@ -25,14 +25,15 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||
return;
|
||||
}
|
||||
|
||||
let args: Vec<_> = match expr.kind {
|
||||
ExprKind::Call(_, args) => args.iter().collect(),
|
||||
ExprKind::MethodCall(_, receiver, args, _) => std::iter::once(receiver).chain(args.iter()).collect(),
|
||||
let (reciever, args) = match expr.kind {
|
||||
ExprKind::Call(_, args) => (None, args),
|
||||
ExprKind::MethodCall(_, receiver, args, _) => (Some(receiver), args),
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let args_to_recover = args
|
||||
let args_to_recover = reciever
|
||||
.into_iter()
|
||||
.chain(args)
|
||||
.filter(|arg| {
|
||||
if cx.typeck_results().expr_ty(arg).is_unit() && !utils::is_unit_literal(arg) {
|
||||
!matches!(
|
||||
|
@ -38,13 +38,11 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tc
|
||||
if expr.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
if let hir::ExprKind::MethodCall(path, recv, args, ..) = expr.kind
|
||||
if let hir::ExprKind::MethodCall(path, recv, [map_arg], ..) = expr.kind
|
||||
&& let Some(sym::Option | sym::Result) = get_type_diagnostic_name(cx, cx.typeck_results().expr_ty(recv))
|
||||
{
|
||||
let (constructor_path, constructor_item) = if let hir::ExprKind::Call(constructor, constructor_args) =
|
||||
recv.kind
|
||||
let (constructor_path, constructor_item) = if let hir::ExprKind::Call(constructor, [arg, ..]) = recv.kind
|
||||
&& let hir::ExprKind::Path(constructor_path) = constructor.kind
|
||||
&& let Some(arg) = constructor_args.first()
|
||||
{
|
||||
if constructor.span.from_expansion() || arg.span.from_expansion() {
|
||||
return;
|
||||
@ -70,9 +68,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tc
|
||||
_ => return,
|
||||
}
|
||||
|
||||
if let Some(map_arg) = args.first()
|
||||
&& let hir::ExprKind::Path(fun) = map_arg.kind
|
||||
{
|
||||
if let hir::ExprKind::Path(fun) = map_arg.kind {
|
||||
if map_arg.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
|
@ -52,8 +52,8 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else if cx.tcx.is_diagnostic_item(sym::from_fn, fun_def_id)
|
||||
&& let [.., last_arg] = args
|
||||
&& let ExprKind::Lit(spanned) = &last_arg.kind
|
||||
&& let [arg] = args
|
||||
&& let ExprKind::Lit(spanned) = &arg.kind
|
||||
&& let LitKind::Str(symbol, _) = spanned.node
|
||||
&& symbol.is_empty()
|
||||
&& let inner_expr_type = cx.typeck_results().expr_ty(inner_expr)
|
||||
|
@ -222,7 +222,7 @@ fn unpack_call_chain<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
|
||||
}
|
||||
|
||||
fn unpack_try<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
|
||||
while let ExprKind::Call(func, [ref arg_0, ..]) = expr.kind
|
||||
while let ExprKind::Call(func, [ref arg_0]) = expr.kind
|
||||
&& matches!(
|
||||
func.kind,
|
||||
ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, ..))
|
||||
@ -244,7 +244,7 @@ fn unpack_match<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
|
||||
/// waited on. Otherwise return None.
|
||||
fn unpack_await<'a>(expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
|
||||
if let ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind {
|
||||
if let ExprKind::Call(func, [ref arg_0, ..]) = expr.kind {
|
||||
if let ExprKind::Call(func, [ref arg_0]) = expr.kind {
|
||||
if matches!(
|
||||
func.kind,
|
||||
ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoFutureIntoFuture, ..))
|
||||
|
@ -153,13 +153,12 @@ fn is_relevant_result_call(cx: &LateContext<'_>, ty: Ty<'_>, method_name: &str)
|
||||
}
|
||||
} else if let ExprKind::Unary(UnOp::Not, expr) = &expr.kind {
|
||||
return collect_unwrap_info(cx, if_expr, expr, branch, !invert, false);
|
||||
} else if let ExprKind::MethodCall(method_name, receiver, args, _) = &expr.kind
|
||||
} else if let ExprKind::MethodCall(method_name, receiver, [], _) = &expr.kind
|
||||
&& let Some(local_id) = path_to_local(receiver)
|
||||
&& let ty = cx.typeck_results().expr_ty(receiver)
|
||||
&& let name = method_name.ident.as_str()
|
||||
&& (is_relevant_option_call(cx, ty, name) || is_relevant_result_call(cx, ty, name))
|
||||
{
|
||||
assert!(args.is_empty());
|
||||
let unwrappable = match name {
|
||||
"is_some" | "is_ok" => true,
|
||||
"is_err" | "is_none" => false,
|
||||
@ -208,7 +207,7 @@ struct MutationVisitor<'tcx> {
|
||||
/// expression: that will be where the actual method call is.
|
||||
fn is_option_as_mut_use(tcx: TyCtxt<'_>, expr_id: HirId) -> bool {
|
||||
if let Node::Expr(mutating_expr) = tcx.parent_hir_node(expr_id)
|
||||
&& let ExprKind::MethodCall(path, ..) = mutating_expr.kind
|
||||
&& let ExprKind::MethodCall(path, _, [], _) = mutating_expr.kind
|
||||
{
|
||||
path.ident.name.as_str() == "as_mut"
|
||||
} else {
|
||||
@ -275,7 +274,7 @@ enum AsRefKind {
|
||||
/// Checks if the expression is a method call to `as_{ref,mut}` and returns the receiver of it.
|
||||
/// If it isn't, the expression itself is returned.
|
||||
fn consume_option_as_ref<'tcx>(expr: &'tcx Expr<'tcx>) -> (&'tcx Expr<'tcx>, Option<AsRefKind>) {
|
||||
if let ExprKind::MethodCall(path, recv, ..) = expr.kind {
|
||||
if let ExprKind::MethodCall(path, recv, [], _) = expr.kind {
|
||||
if path.ident.name == sym::as_ref {
|
||||
(recv, Some(AsRefKind::AsRef))
|
||||
} else if path.ident.name.as_str() == "as_mut" {
|
||||
@ -303,7 +302,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
|
||||
self.visit_branch(expr, cond, else_inner, true);
|
||||
}
|
||||
} else {
|
||||
// find `unwrap[_err]()` calls:
|
||||
// find `unwrap[_err]()` or `expect("...")` calls:
|
||||
if let ExprKind::MethodCall(method_name, self_arg, ..) = expr.kind
|
||||
&& let (self_arg, as_ref_kind) = consume_option_as_ref(self_arg)
|
||||
&& let Some(id) = path_to_local(self_arg)
|
||||
|
@ -129,7 +129,7 @@ fn into_iter_bound<'tcx>(
|
||||
|
||||
/// Extracts the receiver of a `.into_iter()` method call.
|
||||
fn into_iter_call<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>) -> Option<&'hir Expr<'hir>> {
|
||||
if let ExprKind::MethodCall(name, recv, _, _) = expr.kind
|
||||
if let ExprKind::MethodCall(name, recv, [], _) = expr.kind
|
||||
&& is_trait_method(cx, expr, sym::IntoIterator)
|
||||
&& name.ident.name == sym::into_iter
|
||||
{
|
||||
@ -173,7 +173,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
|
||||
}
|
||||
},
|
||||
|
||||
ExprKind::MethodCall(name, recv, ..) => {
|
||||
ExprKind::MethodCall(name, recv, [], _) => {
|
||||
if is_trait_method(cx, e, sym::Into) && name.ident.as_str() == "into" {
|
||||
let a = cx.typeck_results().expr_ty(e);
|
||||
let b = cx.typeck_results().expr_ty(recv);
|
||||
|
@ -5,6 +5,7 @@
|
||||
use rustc_hir::{Closure, Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::borrow::{Borrow, Cow};
|
||||
|
||||
@ -76,19 +77,19 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let ExprKind::Call(func, and_then_args) = expr.kind
|
||||
if let ExprKind::Call(func, [call_cx, call_lint, call_sp, call_msg, call_f]) = expr.kind
|
||||
&& is_expr_path_def_path(cx, func, &["clippy_utils", "diagnostics", "span_lint_and_then"])
|
||||
&& and_then_args.len() == 5
|
||||
&& let ExprKind::Closure(&Closure { body, .. }) = &and_then_args[4].kind
|
||||
&& let ExprKind::Closure(&Closure { body, .. }) = &call_f.kind
|
||||
&& let body = cx.tcx.hir().body(body)
|
||||
&& let only_expr = peel_blocks_with_stmt(body.value)
|
||||
&& let ExprKind::MethodCall(ps, recv, span_call_args, _) = &only_expr.kind
|
||||
&& let ExprKind::Path(..) = recv.kind
|
||||
{
|
||||
let and_then_snippets = get_and_then_snippets(cx, and_then_args);
|
||||
let and_then_snippets =
|
||||
get_and_then_snippets(cx, call_cx.span, call_lint.span, call_sp.span, call_msg.span);
|
||||
let mut sle = SpanlessEq::new(cx).deny_side_effects();
|
||||
match ps.ident.as_str() {
|
||||
"span_suggestion" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => {
|
||||
"span_suggestion" if sle.eq_expr(call_sp, &span_call_args[0]) => {
|
||||
suggest_suggestion(
|
||||
cx,
|
||||
expr,
|
||||
@ -96,11 +97,11 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
&span_suggestion_snippets(cx, span_call_args),
|
||||
);
|
||||
},
|
||||
"span_help" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => {
|
||||
"span_help" if sle.eq_expr(call_sp, &span_call_args[0]) => {
|
||||
let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#);
|
||||
suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), true);
|
||||
},
|
||||
"span_note" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => {
|
||||
"span_note" if sle.eq_expr(call_sp, &span_call_args[0]) => {
|
||||
let note_snippet = snippet(cx, span_call_args[1].span, r#""...""#);
|
||||
suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), true);
|
||||
},
|
||||
@ -125,11 +126,17 @@ struct AndThenSnippets<'a> {
|
||||
msg: Cow<'a, str>,
|
||||
}
|
||||
|
||||
fn get_and_then_snippets<'a, 'hir>(cx: &LateContext<'_>, and_then_snippets: &'hir [Expr<'hir>]) -> AndThenSnippets<'a> {
|
||||
let cx_snippet = snippet(cx, and_then_snippets[0].span, "cx");
|
||||
let lint_snippet = snippet(cx, and_then_snippets[1].span, "..");
|
||||
let span_snippet = snippet(cx, and_then_snippets[2].span, "span");
|
||||
let msg_snippet = snippet(cx, and_then_snippets[3].span, r#""...""#);
|
||||
fn get_and_then_snippets(
|
||||
cx: &LateContext<'_>,
|
||||
cx_span: Span,
|
||||
lint_span: Span,
|
||||
span_span: Span,
|
||||
msg_span: Span,
|
||||
) -> AndThenSnippets<'static> {
|
||||
let cx_snippet = snippet(cx, cx_span, "cx");
|
||||
let lint_snippet = snippet(cx, lint_span, "..");
|
||||
let span_snippet = snippet(cx, span_span, "span");
|
||||
let msg_snippet = snippet(cx, msg_span, r#""...""#);
|
||||
|
||||
AndThenSnippets {
|
||||
cx: cx_snippet,
|
||||
|
@ -243,7 +243,7 @@ fn adjusts_to_slice(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
|
||||
pub fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
|
||||
const ALLOWED_METHOD_NAMES: &[&str] = &["len", "as_ptr", "is_empty"];
|
||||
|
||||
if let ExprKind::MethodCall(path, ..) = e.kind {
|
||||
if let ExprKind::MethodCall(path, _, [], _) = e.kind {
|
||||
ALLOWED_METHOD_NAMES.contains(&path.ident.name.as_str())
|
||||
} else {
|
||||
is_trait_method(cx, e, sym::IntoIterator)
|
||||
|
@ -484,10 +484,9 @@ fn expr(&self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
|
||||
}),
|
||||
ExprKind::If(cond, then, ref otherwise) => self.ifthenelse(cond, then, *otherwise),
|
||||
ExprKind::Binary(op, left, right) => self.binop(op, left, right),
|
||||
ExprKind::Call(callee, args) => {
|
||||
ExprKind::Call(callee, []) => {
|
||||
// We only handle a few const functions for now.
|
||||
if args.is_empty()
|
||||
&& let ExprKind::Path(qpath) = &callee.kind
|
||||
if let ExprKind::Path(qpath) = &callee.kind
|
||||
&& let Some(did) = self.typeck.qpath_res(qpath, callee.hir_id).opt_def_id()
|
||||
{
|
||||
match self.tcx.get_diagnostic_name(did) {
|
||||
|
Loading…
Reference in New Issue
Block a user