Skip to content

add a new rule to detect duplicate switch cases#5849

Open
canvural wants to merge 2 commits into
phpstan:2.2.xfrom
canvural:duplicate-switch-cases
Open

add a new rule to detect duplicate switch cases#5849
canvural wants to merge 2 commits into
phpstan:2.2.xfrom
canvural:duplicate-switch-cases

Conversation

@canvural

@canvural canvural commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Hello 👋🏽

Added a new rule to detect duplicate switch cases. Was debugging some stuff today and turns out we made a typo and the case was matching with another case before it 😅

Added to level 0 with bleeding edge toggle. Let me know if that's not ok.

Closes phpstan/phpstan#712

@VincentLanglet

VincentLanglet commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

I think dead code is reported level 4, but we can be similar to duplicate array keys...

Also, it should close

@canvural

Copy link
Copy Markdown
Contributor Author

I think dead code is reported level 4, but we can be similar to duplicate array keys...

Also, it should close

* [Detect switch case duplicates phpstan#712](https://github.com/phpstan/phpstan/issues/712)

Oh wow, that's an old issue! Test cases I wrote are similar, but do you want me to add a new test case with the code snippet from that issue? I don't think it'll add much though.

@staabm

staabm commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

this test case looks usefull: phpstan/phpstan#712 (comment)

@canvural

Copy link
Copy Markdown
Contributor Author

this test case looks usefull: phpstan/phpstan#712 (comment)

We already have the nonConstantConditions test case, which kinda covers it I think.

}
}

public function looseEqualityIsNotReported(mixed $m): void

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we not report loose comparisons?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cause switch does loose comparison. So they are not duplicates.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cause switch does loose comparison

hmm thats the reason why I think it is a duplicate tbh.

see https://3v4l.org/RVlEU#veol

the "1" case is actually dead code, because a previous loose-compared-equal case already consumed the input

@staabm

staabm commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

should the error be prevented when the case-blocks are not break-ing/return and allow fall-through?

if ($firstSeen === null) {
$seenCases[] = [
'key' => $key,
'printed' => $this->exprPrinter->printExpr($case->cond),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expr printing can be expensive. maybe only remember the $case->cond and print the condition only when building the error?

@ondrejmirtes

Copy link
Copy Markdown
Member

Hi, I'm sorry to crash your party here but I'd imagine this rule differently 😊 It'd make sense to report "always false" conditions by tracking the types in Scope and checking that. We already do that for match - NodeScopeResolver in processExprNode generates "fake" filtering conditions with Identical (because match is doing === comparisons between the cond and arm conds) and in the end invokes new MatchExpressionNode with precise scopes and types which MatchExpressionRule checks.

With FNSR we don't even need those virtual nodes anymore, if we're okay the rule is only going to work when running PHPStan on PHP 8.1+. The rule can just ask for the type of Case_::$cond and thanks to Fibers it will return the correct type.

Looking at Switch_ handling in NodeScopeResolver we might actually be pretty close to achieving that.

Feel free to create an issue with this description and feed it to the bot (Claude) 😊

@ondrejmirtes

Copy link
Copy Markdown
Member

There's now #5854 - how do you like it when compared to this PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Detect switch case duplicates

4 participants