Skip to content

UselessCastRule on native types is auto-fixable - #344

Open
staabm wants to merge 3 commits into
phpstan:2.1.xfrom
staabm:useless-auto
Open

staabm wants to merge 3 commits into
phpstan:2.1.xfrom
staabm:useless-auto

Conversation

@staabm

@staabm staabm commented Oct 31, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@staabm

staabm commented Oct 31, 2026

Copy link
Copy Markdown
Contributor Author

//cc @SanderMuller

@staabm
staabm requested a review from VincentLanglet October 31, 2026 09:25
@staabm
staabm marked this pull request as ready for review October 31, 2026 09:25
@staabm
staabm requested a balanced review from Copilot October 31, 2026 09:26

This comment was marked as outdated.

@VincentLanglet VincentLanglet left a comment

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.

Is there a reason to only auto-fix native type ?
Is there a strategy which was already used ?

@staabm

staabm commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor Author

Is there a reason to only auto-fix native type ?

people mostly use phpdoc types when they are not 100% sure whether these hold in all cases. we want auto-fixers to only change code if we are 100% confident about consequences. we don't want suprises because actual runtime types differ from what we work with.

e.g. https://3v4l.org/5b3vO#v could have bad consequences when we handle it like a int even though at runtime its not

Is there a strategy which was already used ?

I am not exactly sure what you mean. I have been doing auto-fixing stuff in e.g. https://github.com/phpstan/phpstan-phpunit/pulls?q=sort%3Aupdated-desc+is%3Apr+state%3Aclosed+auto-fixable in the past and I did it a similar way here.

does this answer your question?

@VincentLanglet

Copy link
Copy Markdown
Contributor

You can still have false-positive with native type for people not using the Array String Keys feature.
https://phpstan.org/r/952b81a1-80df-4d79-b1ce-10b2f6b56d46

@staabm

staabm commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor Author

thats a great example. I think we could harden the logic by auto-fixing string casts only for property-fetches.

do you have more examples in mind?

@VincentLanglet

Copy link
Copy Markdown
Contributor

do you have more examples in mind?

No the only known reported "false positive" was the famous string key for array.

@SanderMuller SanderMuller left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I ran the fixer on some extra cases with native types only. The PR's own tests pass. These changed the code in a way that breaks it:

  • $b = $integer-(int)-$integer; becomes $b = $integer--$integer;, which is a parse error.
  • foreach ((array) $array as &$v) with array $array becomes foreach ($array as &$v). The loop then writes to $array, not to a copy. In my run the array changed from [1,2] to [0,0].
  • Vincent's case: strlen((string) $k) becomes strlen($k), and with strict types that throws a TypeError for the key '1'.

These two are less clear, because the cast is already reported today:

  • (int) $countable->count() loses its cast, because Countable::count() has a tentative int return type. A class that implements count() without a return type can still return '5'. PHP only shows a deprecation for that.
  • (int) ($integer * PHP_INT_MAX) loses its cast, and the result is a float at runtime.

A small one: (int) /* why */ $integer becomes $integer, so the comment is lost.

If the fixer only removes casts around property fetches, for all cast types, it skips every case above except the foreach one. That one stays, because foreach ((array) $this->items as &$v) writes to the property in the same way. To fix that, the fixer could skip the cast when it is the expression of a by-ref foreach.

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.

4 participants