reproduce specifier bug
with https://github.com/phpstan/phpstan-src/pull/1383/files#r887647098 I was running into this bug.
the problem is, that phpstan should dump the type string but reports bool|float|int|string for the dumpType call seen here:
$ php bin/phpstan analyze src/Analyser/TypeSpecifier.php
Note: Using configuration file C:\dvl\Workspace\phpstan-src-staabm\phpstan.neon.dist.
1/1 [============================] 100%
------ ------------------------------------
Line TypeSpecifier.php
------ ------------------------------------
274 Dumped type: bool|float|int|string
------ ------------------------------------
I am not yet sure how to debug this issue further. I also tried reproducing the case in a smaler repro script, but this did not work out yet.
any ideas/hints?
I guess I'd try using xdebug here, in case you didn't do that already.
I tried, but wasn't sure where to look tbh
after a bit more trying, I was able to reduce the repro further
this PR now includes a proper NodeScopeResolverTest for the problem
Check this strange behavior as well:
- https://phpstan.org/r/889e3c66-972b-4ace-af00-e9beb3280918 (with
dumpType($constantType)) - https://phpstan.org/r/1e85e658-425f-44ef-afeb-7243c3df5221 (without
dumpType($constantType))
@rvanvelzen @rajyan might one of you guys has time to look into this problem?
I've looked into this recently but it didn't look trivial to solve. I'm a bit swamped at work right now but I'll look into it more when that settles down again :)
@staabm This was harder to solve than I thought. You can see https://github.com/phpstan/phpstan-src/pull/1495 when $var is specified, you might narrow down $var->call() more. In this case, $var->call() is specified as non-null at first, and the next instanceof ConstantString type can specify $var->call() more. Currently, these types of type specification is not handled.
after working thru this I implemented several different solutions, which made the test pass, but regressed other things.
by doing this I got a better understanding how things work and how a possible solution could look like.
atm I think we need to adjust this block: https://github.com/phpstan/phpstan-src/blob/b0babd082514303ec62deb5f16cf330f845c1821/src/Analyser/MutatingScope.php#L3551-L3579
.. so it takes into account when a variable get specified to a new ObjectType - e.g. via $constantType instanceof ConstantStringType.
We need to update all moreSpecificTypeHolders which depend on $constantType , e.g. $constantType->getValue() and merge the existing type of $constantType->getValue() with the new knowledge that $var was specified to ConstantStringType and therefore we have a better idea of $constantType->getValue().
class HelloWorld
{
public function doFoo(
ConstantScalarType $constantType
)
{
if ($constantType->getValue() === null) {
return;
}
assertType('bool|float|int|string', $constantType->getValue());
if (
$constantType instanceof ConstantStringType
) {
assertType('string', $constantType->getValue());
}
}
}
in the end I think this is a similar thing, this line achieves for array-offset-types: https://github.com/phpstan/phpstan-src/blob/b0babd082514303ec62deb5f16cf330f845c1821/src/Analyser/MutatingScope.php#L3577
finally, this one is ready for review.
Is this still a problem?
The underlying bug should still be present, but in phpstan-src I worked arround it in a related PR, so the phpstan-src codebase is no longer blocked by it right now
It'd be better to reproduce this on phpstan.org/try and open an issue.