Skip to content

implement gettype() return type extension #2437

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 19, 2023

Conversation

staabm
Copy link
Contributor

@staabm staabm commented Jun 6, 2023


$valueType = $scope->getType($functionCall->getArgs()[0]->value);

$type = TypeTraverser::map($valueType, static function (Type $valueType, callable $traverse): Type {
Copy link
Contributor Author

@staabm staabm Jun 6, 2023

Choose a reason for hiding this comment

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

alternatively we might implement Type->getType() or Type->getTypeString() instead

@staabm staabm marked this pull request as ready for review June 6, 2023 09:35
@phpstan-bot
Copy link
Collaborator

This pull request has been marked as ready for review.

if (
$leftType instanceof ConstantScalarType
&& !$binaryOperation->right instanceof Node\Scalar\String_
Copy link
Member

Choose a reason for hiding this comment

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

Eh, what's so special about string? Why did you add this change?

Copy link
Contributor Author

@staabm staabm Jun 6, 2023

Choose a reason for hiding this comment

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

its required to make https://github.com/staabm/phpstan-src/blob/1.10.x/tests/PHPStan/Analyser/data/bug-6901.php pass

otherwise - because of switch beeing re-written to comparisons and the new return type extension - $leftType and $rightType will resolve to constant strings and the method - as it was before the PR - would not specify the FuncCall expression but the String_

Copy link
Member

Choose a reason for hiding this comment

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

That feels like a wrong placement for such fix.

gettype is handled in TypeSpecifier around line 1072. Wouldn't it help to first check for gettype condition and only after that to perform the thing on line 1424?

Copy link
Contributor Author

@staabm staabm Jun 7, 2023

Choose a reason for hiding this comment

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

I think we will have the same problem for other functions being used in a switch statement/identical comparison and have a return type extension with constant scalars.

we cannot detect it in line 1072, as the problem is not within the FuncCall itself, but the comparison.

see the bug in action in https://phpstan.org/r/d00e29f6-3163-414b-b83d-f591fd1eaf7d
(I have added a separate test-case for it in e60ff34)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you prefer we could separate that bugfix in a new PR

Copy link
Member

Choose a reason for hiding this comment

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

Yeah https://phpstan.org/r/d00e29f6-3163-414b-b83d-f591fd1eaf7d shouldn't be happening, but I'm not sure if it's the same bug...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok, turned it into a separate bug: phpstan/phpstan#9404

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had another look at it.

you were right that phpstan/phpstan#9404 does not related to the problem here.

I think the fix is right though and the description in https://github.com/phpstan/phpstan-src/pull/2437/files#r1220239214 is accurate

Copy link
Contributor Author

@staabm staabm Jun 8, 2023

Choose a reason for hiding this comment

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

to simplify the test in question:

<?php

use function PHPStan\Testing\assertType;

/**
 * @param int $y
 */
function foo($y): void
{
	switch (gettype($y)) {
		case "integer":
			assertType('int', $y);
			break;
		default:
			assertType('*NEVER*', $y);
	}
}

runs into

------ ------------------------------------ 
  Line   tst.php                             
 ------ ------------------------------------ 
  15     Expected type *NEVER*, actual: int  
 ------ ------------------------------------ 

in this PR, when we drop the ... instanceof Node\Scalar\String_ changes

fixed mixed type

fixed default return

another test-case
@ondrejmirtes
Copy link
Member

As I said, I didn't like the changes in TypeSpecifier. I made some changes on 1.10.x, essentially doing this #2437 (comment)

And now the tests in your PR pass. I'm gonna merge it if the pipeline is going to be green. Thanks.

@ondrejmirtes ondrejmirtes merged commit aa66b84 into phpstan:1.10.x Jun 19, 2023
@staabm staabm deleted the gettype2 branch June 20, 2023 04:47
@staabm
Copy link
Contributor Author

staabm commented Jun 20, 2023

Thanks

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.

None yet

3 participants