From f252df76c482184180f4e2770734c207881fc10e Mon Sep 17 00:00:00 2001 From: Brian Foley Date: Wed, 14 Oct 2026 21:25:41 +0100 Subject: [PATCH] Ignore unused function params prefixed with `_` Like variable assignment in UnusedVariableRule and similar to Rust, Python, and GoLang linting rules: Go treats arguments named `_` as dummy arguments. Rust uses the same rule for unused variables and function params. Python's ruff uses _prefix for unused-function-argument - https://docs.astral.sh/ruff/rules/unused-function-argument/ - https://doc.rust-lang.org/stable/rustc/lints/listing/warn-by-default.html#unused-variables - https://tip.golang.org/gopls/analyzers#unusedparams Fixes phpstan/phpstan#15480 --- src/Rules/UnusedParametersCheck.php | 4 ++++ .../data/unused-function-parameters.php | 22 +++++++++++++++++++ .../data/unused-input-value-flow.php | 6 +++++ 3 files changed, 32 insertions(+) diff --git a/src/Rules/UnusedParametersCheck.php b/src/Rules/UnusedParametersCheck.php index 37b4791a1cb..75614995cd7 100644 --- a/src/Rules/UnusedParametersCheck.php +++ b/src/Rules/UnusedParametersCheck.php @@ -14,6 +14,7 @@ use function is_string; use function ltrim; use function sprintf; +use function str_starts_with; /** * The per-parameter half of the unused-parameter rules, on top of the @@ -61,6 +62,9 @@ public function getUnusedParameterErrors( if (!$parameter->var instanceof Variable || !is_string($parameter->var->name)) { continue; } + if (str_starts_with($parameter->var->name, '_')) { + continue; + } if (isset($contractParameterNames[$parameter->var->name])) { continue; } diff --git a/tests/PHPStan/Rules/Functions/data/unused-function-parameters.php b/tests/PHPStan/Rules/Functions/data/unused-function-parameters.php index 04aab07cffc..b38db7b38fa 100644 --- a/tests/PHPStan/Rules/Functions/data/unused-function-parameters.php +++ b/tests/PHPStan/Rules/Functions/data/unused-function-parameters.php @@ -113,3 +113,25 @@ function observedByFuncGetArg(int $x): array return [func_get_arg(0), $x]; } + +function completelyUnusedIgnore(int $used, $_ignoredUnused): int +{ + return $used; +} + +function byRefUnusedIgnore(int &$_ignoredX): void +{ + echo 'no use of the reference'; +} + +function variadicIgnoredUnusedIgnore(int $used, int ...$_ignoredRest): int +{ + return $used; +} + +function usedViaResolvedVariableVariableIgnore(int $secret, int $_ignoredOther): int +{ + $name = 'secret'; + + return $$name; +} diff --git a/tests/PHPStan/Rules/Functions/data/unused-input-value-flow.php b/tests/PHPStan/Rules/Functions/data/unused-input-value-flow.php index 2e9080a2947..49849d18b1f 100644 --- a/tests/PHPStan/Rules/Functions/data/unused-input-value-flow.php +++ b/tests/PHPStan/Rules/Functions/data/unused-input-value-flow.php @@ -57,3 +57,9 @@ function overwrittenParameter(int $input): int $input = 1; return $input; } + +function overwrittenParameterIgnore(int $_ignoredInput): int +{ + $_ignoredInput = 1; + return $_ignoredInput; +}