Skip to content

Fix phpstan/phpstan#10690: Using a Trait with many private const triggers: "Constant is unused. "#5320

Open
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-tgmlogn
Open

Fix phpstan/phpstan#10690: Using a Trait with many private const triggers: "Constant is unused. "#5320
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-tgmlogn

Conversation

@phpstan-bot
Copy link
Copy Markdown
Collaborator

Summary

When a trait defines private constants and multiple classes use the trait, any class that doesn't reference all the trait's constants would get false "Constant is unused" errors. The fix skips the unused constant check for constants that originate from a trait.

Changes

  • Added src/Node/ClassConstant.php — wrapper class (mirrors ClassMethod) that pairs a ClassConst node with isDeclaredInTrait() info
  • Updated src/Node/ClassStatementsGatherer.php — wraps ClassConst nodes in ClassConstant using $scope->isInTrait()
  • Updated src/Node/ClassConstantsNode.php — added getClassConstants() returning ClassConstant[]; existing getConstants() preserved for backward compatibility
  • Updated src/Rules/DeadCode/UnusedPrivateConstantRule.php — uses getClassConstants() and skips trait-declared constants
  • Added tests/PHPStan/Rules/DeadCode/data/bug-10690.php — regression test
  • Added testBug10690() in tests/PHPStan/Rules/DeadCode/UnusedPrivateConstantRuleTest.php

Root cause

UnusedPrivateConstantRule checks all private constants in a class and reports any that aren't referenced within that class. When a trait defines private constants and a class uses that trait, the constants appear in the class's constant list. If the class doesn't use all trait constants, the rule incorrectly reported them as unused. The fix follows the same pattern used for private properties and methods (isDeclaredInTrait()): constants declared in traits are skipped since the trait author intended them to be available across all users of the trait.

Test

Added a regression test with a trait MyTrait defining two private constants (AAA, BBB), used by two classes — First uses both, SecondConsumer uses only AAA. The test expects no errors, confirming that BBB is not falsely reported as unused in SecondConsumer.

Fixes phpstan/phpstan#10690

…it constants

- Added ClassConstant wrapper class (similar to ClassMethod) that tracks isDeclaredInTrait
- Updated ClassStatementsGatherer to wrap ClassConst nodes with trait context
- Updated ClassConstantsNode with getClassConstants() method preserving backward compatibility
- UnusedPrivateConstantRule now skips constants declared in traits
- Added regression test in tests/PHPStan/Rules/DeadCode/data/bug-10690.php
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.

1 participant