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:
bors 2024-10-13 13:34:48 +00:00
commit 236751d093
59 changed files with 127 additions and 149 deletions

View file

@ -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, ..))
),

View file

@ -106,9 +106,9 @@ fn is_method(
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;
}

View file

@ -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

View file

@ -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() {

View file

@ -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);

View file

@ -321,7 +321,10 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, '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;

View file

@ -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

View file

@ -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()

View file

@ -10,7 +10,7 @@ use rustc_middle::mir::{Location, START_BLOCK};
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)

View file

@ -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;

View file

@ -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());

View file

@ -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))
{

View file

@ -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))
{

View file

@ -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 {

View file

@ -9,8 +9,7 @@ use super::UNINIT_ASSUMED_INIT;
/// 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))
{

View file

@ -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)