Skip to content
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

Utilize composer min-php version to narrow PHP_VERSION_ID #2968

Closed
wants to merge 13 commits into from

Conversation

staabm
Copy link
Contributor

@staabm staabm commented Mar 13, 2024

idea is to catch errors like Roave/BetterReflection#1406 (comment) in which bogus conditions like if (PHP_VERSION_ID >= 80100) {} have been used in tests.

it's a bug in the linked case, because the project itself only supports "php": "~8.2.0 || ~8.3.2",.
Since CI only is running against in composer.json declared supported versions this error was not spotted before.

Copy link
Member

@ondrejmirtes ondrejmirtes left a comment

Choose a reason for hiding this comment

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

Do the upper bound too - so that we know ^8.1 cannot be 9.

@staabm
Copy link
Contributor Author

staabm commented Mar 13, 2024

@ondrejmirtes what do you think about all these

Comparison operation "<" between int<80100, max> and 80100 is always false.

errors? should we ignore them via phpstan.neon or should we add e.g. a feature flag, so we can disable the composer based min/max-php version?

@ondrejmirtes
Copy link
Member

It's not really generally usable. In PHPStan and many other apps, the constraint in composer.json does nor say anything about production environment, or can be outdated.

It could be:

  • On in bleeding edge
  • But at the same time there should be a way to turn it off, or make it configurable manually, like reading the range from phpstan.neon instead of composer.json. phpVersion behaves similarly, when it's null, we try to detect it.

@clxmstaab clxmstaab force-pushed the min-php branch 2 times, most recently from 8c64205 to 6dbb9d1 Compare March 13, 2024 15:39
@@ -671,7 +671,7 @@ public function testBug8068(): void

public function testBug6243(): void
{
if (PHP_VERSION_ID < 704000) {
Copy link
Contributor Author

@staabm staabm Mar 13, 2024

Choose a reason for hiding this comment

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

found a bug in a pre-existing test -> #3254

Comment on lines 40 to 41
$config['parameters']['minPhpVersion'] = 70100;
$config['parameters']['maxPhpVersion'] = 90000;
Copy link
Contributor Author

@staabm staabm Mar 13, 2024

Choose a reason for hiding this comment

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

I put the min/max php version here, so we have a fixed upper/lower bound in phpstan-src, but all projects per default still use composer.json based auto-php-version bounds. I think even projects using bleeding-edge would benefit from automatic php version bounds.

the case that projects need to opt-out from this check will be rare I guess - but is possible via the new phpstan.neon parameters by defining custom versions

@staabm
Copy link
Contributor Author

staabm commented Mar 13, 2024

I think the errors we see in CI make sense. not sure what we can/should do about them.

it make sense to check for php-versions smaller then the composer.json declared supported ones, to be super safe.
maybe I should use composer-min-version - 1 as a lower bound?

edit: did just that with 0d398ab

@staabm staabm marked this pull request as ready for review March 13, 2024 16:06
@phpstan-bot
Copy link
Collaborator

This pull request has been marked as ready for review.

@staabm staabm force-pushed the min-php branch 2 times, most recently from 982b705 to eb63e2a Compare March 18, 2024 08:09
@clxmstaab clxmstaab force-pushed the min-php branch 2 times, most recently from e7c38fc to 0a2f82f Compare March 18, 2024 09:33
@staabm staabm marked this pull request as draft March 18, 2024 09:39
@staabm staabm marked this pull request as ready for review March 18, 2024 10:03
@phpstan-bot
Copy link
Collaborator

This pull request has been marked as ready for review.

@staabm
Copy link
Contributor Author

staabm commented Mar 22, 2024

@ondrejmirtes keeping this one up2date is a bit cumbersome, because of the added composer dependency (and the conflicts I need to resolve on every other dependency update).

would be great if you could find the time to move it forward.

Copy link
Member

@ondrejmirtes ondrejmirtes left a comment

Choose a reason for hiding this comment

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

Some thoughts about this PR:

  1. There are more constants related to PHP versions: https://www.php.net/manual/en/reserved.constants.php
  2. To be really useful, this should also influence version_compare: https://www.php.net/manual/en/function.version-compare.php A dynamic return type extension would be sufficient.
  3. I'd like phpVersion to be either: null, a single number, or a structure with min/max

If it's null, resolve it to a single number in PHPStan 1.x (according to config.platform.php in composer.json), and to min/max structure with bleeding edge (according to require.php in composer.json).

If it's a single number, keep today's behaviour. Meaning PHP_VERSION_ID is not going to be limited.

If it's min/max, clamp PHP_VERSION_ID and other constants to be an IntegerRangeType.

Also we should have some kind of warning if the values don't make sense. max should be >= min.

@staabm
Copy link
Contributor Author

staabm commented Mar 24, 2024

thanks for the feedback.

If it's null, resolve it to a single number in PHPStan 1.x (according to config.platform.php in composer.json), and to min/max structure with bleeding edge (according to require.php in composer.json).

If it's a single number, keep today's behaviour. Meaning PHP_VERSION_ID is not going to be limited.

If it's min/max, clamp PHP_VERSION_ID and other constants to be an IntegerRangeType.

this means in case of a configured min/max version, we don't have a concrete version anymore in PhpVersion.
so all the support-methods don't work like they do today. since PhpVersion is tagged @api I cannot change it to return a Trinary..

public function supportsNullCoalesceAssign(): bool
{
return $this->versionId >= 70400;
}

@ondrejmirtes
Copy link
Member

That's right. Changing all these methods to a TrinaryLogic would be a costly refactoring that would eventually lead to ReflectionClass::hasClass() also returning TrinaryLogic. I'd like that but not at this point.

Please try using the min value as the origin for these methods to decide whether to return true or false.

@ondrejmirtes
Copy link
Member

If that's not going to work for some reason then I'm not interested in this PR at this point, sorry. When investing in an area we need to do something that makes sense, not just a minimal amount of work that would change the interpretation of a single constant.

@staabm
Copy link
Contributor Author

staabm commented Mar 24, 2024

Sure, lets see how it goes.

Alternatively/Additionally I will look into a narrowed PhpVersion based on scope like we brainstormed in phpstan/phpstan#4212 (reply in thread)

src/Php/ComposerPhpVersionFactory.php Show resolved Hide resolved
)
{
if (is_int($phpVersion)) {
return;
Copy link
Member

Choose a reason for hiding this comment

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

I think this if can be just removed.

Copy link
Contributor Author

@staabm staabm Jun 2, 2024

Choose a reason for hiding this comment

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

re-added this line, which fixed the build.

errors before the fix can be seen in e.g. https://github.com/phpstan/phpstan-src/actions/runs/9331440117/job/25686106757?pr=2968

src/Php/ComposerPhpVersionFactory.php Outdated Show resolved Hide resolved
src/Php/ComposerPhpVersionFactory.php Outdated Show resolved Hide resolved
src/Php/ComposerPhpVersionFactory.php Outdated Show resolved Hide resolved
src/Php/PhpVersionFactoryFactory.php Outdated Show resolved Hide resolved
@staabm
Copy link
Contributor Author

staabm commented Jun 1, 2024

All feedback should be addressed.

Yeah, please remove the -1.

because of this change we are now seeing a lot of errors in the test-suite, e.g.:

Comparison operation "<" between int<80100, 90000> and 80100 is always false.

should these be ignored globally? any other idea on how to handle these?

resolved with edde1b6, see #2968 (comment)


random idea: use a separate error-identifier for these errors?

@staabm staabm marked this pull request as ready for review June 1, 2024 15:53
@phpstan-bot
Copy link
Collaborator

This pull request has been marked as ready for review.

return $composerPhpVersion;
}

private function buildVersion(string $minVersion): ?PhpVersion
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
private function buildVersion(string $minVersion): ?PhpVersion
private function buildVersion(string $version): ?PhpVersion

@@ -17,11 +17,26 @@ public function getVersionId(): int
return $this->versionId;
}

public function getMajor(): int
{
return (int) floor($this->versionId / 10000);
Copy link
Contributor

Choose a reason for hiding this comment

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

intdiv would be better

try {
$composerJsonContents = FileReader::read($composerJsonPath);
$composer = Json::decode($composerJsonContents, Json::FORCE_ARRAY);
$requiredVersion = $composer['require']['php'] ?? null;
Copy link
Contributor

Choose a reason for hiding this comment

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

phpstan/phpstan#9256 should be probably implemented in this PR as well and tested.

Copy link
Member

Choose a reason for hiding this comment

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

That's unrelated and can be done later.

staabm and others added 13 commits July 20, 2024 23:20
fix

Update e2e-tests.yml

add more tests

fix

rename class

added config parameters

fix test

more tests

test version parameters

Update e2e-tests.yml

prevent 'Comparison operation "<" between int<70205, 90000> and 70205 is always false.' strict errors

downgrade composer/semver for brianium/paratest:4.0.0 compat

should fix the php 7.2 CI build

incorporate feedback

spaces to tabs

support more constants

Narrow `PHP_VERSION` in version_compare()

another test

fix
@staabm
Copy link
Contributor Author

staabm commented Oct 26, 2024

rebased for 2.x in #3584

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.

5 participants