Skip to content

Report impossible class_exists/interface_exists/trait_exists/enum_exists#5754

Open
janedbal wants to merge 2 commits into
phpstan:2.1.xfrom
janedbal:struct-exists-impossibility
Open

Report impossible class_exists/interface_exists/trait_exists/enum_exists#5754
janedbal wants to merge 2 commits into
phpstan:2.1.xfrom
janedbal:struct-exists-impossibility

Conversation

@janedbal
Copy link
Copy Markdown
Contributor

Detect via reflection when the constant-string argument names a struct of the wrong kind (e.g. class_exists() on an interface name) and narrow the argument to never in the truthy context. Drop the ImpossibleCheckTypeHelper bailout for these four functions so the rule can pick up the impossibility, while still suppressing "always true" since runtime autoload can fail.

Closes phpstan/phpstan#14683

@phpstan-bot
Copy link
Copy Markdown
Collaborator

You've opened the pull request against the latest branch 2.2.x. PHPStan 2.2 is not going to be released for months. If your code is relevant on 2.1.x and you want it to be released sooner, please rebase your pull request and change its target to 2.1.x.

@janedbal janedbal force-pushed the struct-exists-impossibility branch from 3dc802f to 480fc5b Compare May 25, 2026 07:55
@janedbal janedbal changed the base branch from 2.2.x to 2.1.x May 25, 2026 07:55
@janedbal janedbal force-pushed the struct-exists-impossibility branch from 480fc5b to 95f21da Compare May 25, 2026 07:57
Detect via reflection when the constant-string argument names a struct
of the wrong kind (e.g. class_exists() on an interface name) and
narrow the argument to never in the truthy context. Drop the
ImpossibleCheckTypeHelper bailout for these four functions so the rule
can pick up the impossibility, while still suppressing "always true"
since runtime autoload can fail.

Closes phpstan/phpstan#14683
@janedbal janedbal force-pushed the struct-exists-impossibility branch from 95f21da to d04d50c Compare May 25, 2026 10:19
@phpstan-bot
Copy link
Copy Markdown
Collaborator

This pull request has been marked as ready for review.

$argsCount = count($args);
if ($node->name instanceof Node\Name) {
$functionName = strtolower((string) $node->name);
if (in_array($functionName, [
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.

Given the fact this condition is now useless for 200 lines of code, I feel like it would be better moving the onlyReportFalse declaration.

This way we have

if ($node instanceof FuncCall) {
     // specific logic which could be moved into a private or a dedicated service
}

$onlyReportFalse = ...;

// genericLogic

Maybe one day the

$onlyReportFalse = ...;

will become a

$onlyReportValue = // true/false/null

WDYT @staabm ?

@VincentLanglet VincentLanglet requested a review from staabm May 25, 2026 18:53
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.

missing "is always false/true" errors on class_exists, method_exists, ..

3 participants