Skip to content

Fix NumericReturnTypeFromStrictScalarReturnsRector for non-natively-typed parameters#4380

Merged
TomasVotruba merged 16 commits intorectorphp:mainfrom
staabm:int-range
Jul 3, 2023
Merged

Fix NumericReturnTypeFromStrictScalarReturnsRector for non-natively-typed parameters#4380
TomasVotruba merged 16 commits intorectorphp:mainfrom
staabm:int-range

Conversation

@staabm
Copy link
Copy Markdown
Contributor

@staabm staabm commented Jun 30, 2023

No description provided.

@staabm staabm requested a review from TomasVotruba as a code owner June 30, 2023 07:52
$rightType = $this->getType($binaryOp->right);

if ($leftType instanceof IntegerType && $rightType instanceof IntegerType) {
if ($leftType->isInteger()->yes() && $rightType->isInteger()->yes()) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

how should this rector behave according to phpdoc typed params?

does the "strict" in the rector name mean it should only trust native types?

Copy link
Copy Markdown
Contributor Author

@staabm staabm Jun 30, 2023

Choose a reason for hiding this comment

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

I am thinking about a test like

<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\NumericReturnTypeFromStrictScalarReturnsRector\Fixture;

final class SkipPhpDoc
{
    /**
     * @param 0|1 $first
     */
    public function resolve($first, int $second)
    {
        return $first + $second;
    }
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Docblocks are skipped as non-strict types.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you add test fixture with this code sample to make sure its still skipped?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There is ExprAnalyzer for detect variable from non typed param for that

public function isNonTypedFromParam(Expr $expr): bool

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@staabm could you verify latest change of ExprAnalyzer->isNonTypedFromParam() works on this? Thank you.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

it seems it works - thank you

$rightType = $this->getType($binaryOp->right);

if ($leftType instanceof IntegerType && $rightType instanceof IntegerType) {
if ($leftType->isInteger()->yes() && $rightType->isInteger()->yes()) {
Copy link
Copy Markdown
Member

@TomasVotruba TomasVotruba Jul 2, 2023

Choose a reason for hiding this comment

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

How can we verify this takes into account only direct integers? I'd prefer to be explicit and keep/extend the original code, instead of hoping it avoid docblock integer types, that are interprested as strict types by PHPStan.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I thought I did by adding more tests. Do you have something concrete in mind which should be tested in addition?

I think we can't just add instanceof IntegerRangeType because there is also a union of integers in the game.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I recall doc typed properties and external method/property calls are false positives. Could you add those too?

Copy link
Copy Markdown
Contributor Author

@staabm staabm Jul 3, 2023

Choose a reason for hiding this comment

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

I reverted my implementation changes for now, as you are right in that phpdoc typed properties are a problem.
these are a problem even before the changes I suggested before this initial PR.

I re-calibrated the goal of this PR to just add more test-cases for now, so this knowledge about edge cases of this rector is not lost.


I got the feeling the only real way this rector could work reliably is if it would use treatPhpDocTypesAsCertain: false. is this something we could configure on a per rector basis?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Rector can specify phpstan file to be used:

$rectorConfig->phpstanConfig(__DIR__ . '/phpstan-for-rector.neon');

Copy link
Copy Markdown
Contributor Author

@staabm staabm Jul 3, 2023

Choose a reason for hiding this comment

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

I guess this setting would then affect all rector rules not just a one.

I wonder whether rector should have a "mode" in which it does not at all trust phpdoc, so it can be very sure about the things it is doing. just applying treatPhpDocTypesAsCertain: false would regress a lot of existing functionality I guess.

@staabm staabm changed the title Support IntegerRangeType in NumericReturnTypeFromStrictScalarReturnsRector Cover more edge cases in NumericReturnTypeFromStrictScalarReturnsRectorTest Jul 3, 2023
@staabm
Copy link
Copy Markdown
Contributor Author

staabm commented Jul 3, 2023

I have reduced the PR to the important test-cases as I think the initial goal would require some things we can't do?

@staabm staabm changed the title Cover more edge cases in NumericReturnTypeFromStrictScalarReturnsRectorTest Fix NumericReturnTypeFromStrictScalarReturnsRector for non-natively-typed parameters Jul 3, 2023
@TomasVotruba
Copy link
Copy Markdown
Member

Thanks 👍

Lets merge this as it is and iterate from there. Checking only variables or disabling doc types might be an option.

@TomasVotruba TomasVotruba merged commit 265f3ac into rectorphp:main Jul 3, 2023
@staabm staabm deleted the int-range branch July 3, 2023 08:40
@staabm
Copy link
Copy Markdown
Contributor Author

staabm commented Jul 3, 2023

disabling doc types might be an option

how can this be achieved?

@samsonasik
Copy link
Copy Markdown
Member

@staabm I think that need failing test case first, to check the rule that affected, and we can see possible solution to compare type vs native type. On this case, verify if the data is property fetch, then check property type itself via Reflection.

@TomasVotruba
Copy link
Copy Markdown
Member

TomasVotruba commented Jul 3, 2023

@staabm I was referring to PHPStan option: #4380 (comment)
Not sure how it's implemented in PHPStan, it's been couple of years since I looked into this parameter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants