Add phpIntSize parameter, infer 64bit from composer.json under bleeding edge#6030
Add phpIntSize parameter, infer 64bit from composer.json under bleeding edge#6030zonuexe wants to merge 2 commits into
Conversation
|
I feel like that if such option was introduce it should support the |
|
That's a fair thing to expect from the name, and it was my first instinct too. What stopped me is that
\PHPStan\dumpType(3000000000); // 3000000000
\PHPStan\dumpType(2147483647 + 1); // 2147483648
\PHPStan\dumpType(1 << 40); // 1099511627776Setting Making
That is option (1) in phpstan/phpstan#14948, which is what #11711 declined. This PR doesn't pick a platform. The default stays If someone does need 32bit analysis, running PHPStan on a 32bit build already gets most of the way there, since the engine inherits its integer width from the process. 32bit is a thin release target in 2026, and the person writing PHP on a Raspberry Pi is coding and debugging on a 64bit machine. If the name is what invites |
Refs phpstan/phpstan#14948
Option (3) from that issue, the first step of the rollout in section 6. I'm opening it so the discussion has code to look at. There's no rush to merge it. If you'd rather go straight to (2) and drop the 32bit branch, say so and I'll close this.
What it does
phpIntSize: 8pins the three constants to their 64bit values:phpIntSize: 8PHP_INT_MAX2147483647|92233720368547758079223372036854775807PHP_INT_MIN-9223372036854775808|-2147483648-9223372036854775808PHP_INT_SIZE4|88PHP_INT_MAX + 12147483648|9.223372036854776E+189.223372036854776E+18The last row is the one from the issue: under the default, no PHP build can hold that
int(2147483648).The parameter defaults to
null, so nothing changes for anyone who doesn't set it.Why the schema rejects
phpIntSize: 4Integer literals, overflow to float, and
IntegerRangeType's bounds are all fixed at 64bit. Accepting4would let a user opt into "PHP_INT_MAXis2147483647, but2147483647 + 1isint(2147483648)", which is the same contradiction the union has today.Real 32bit semantics could come from either side. Emulate them in the engine, or run PHPStan on a 32bit build of PHP, which gets most of the way there since the engine inherits its integer width from the process it runs in. I doubt either is worth the effort.
anyOf(8)leaves room to add4if that changes.Why I pin
PHP_INT_SIZEtooLeaving it as
4|8would keepif (PHP_INT_SIZE === 4)branches alive whilePHP_INT_MAXinside them is the 64bit value. Pinned, PHPStan reportsidentical.alwaysFalseon those branches, which is the answer a project asked for when it opted in. A library that still supports 32bit should not setphpIntSize.ConstantResolverkeeps its existing guard on the host'sPHP_INT_SIZE, since PHPStan running on 32bit cannot constructConstantIntegerType(9223372036854775807).Bleeding edge:
composerPhp64BitComposer registers the
php-64bitvirtual package only whenPHP_INT_SIZE === 8(PlatformRepository.php), andAutoloadGenerator::getPlatformCheck()emits aPHP_INT_SIZE !== 8assertion intovendor/composer/platform_check.php. A project that requires it is 64bit at install time and at runtime.So
require."php-64bit"in composer.json can implyphpIntSize: 8with no configuration. But that turns the feature on for projects that never asked, and they would start seeingidentical.alwaysFalseon theirPHP_INT_SIZE === 4branches plus different types whereverPHP_INT_MAXflows. I put it behind thecomposerPhp64Bitfeature toggle.phpIntSizeworks without the toggle and wins over composer.json.php-64bitalso constrains the PHP versionComposerPhpVersionFactoryreadsrequire.phpand nothing else, so the project above gets nophpVersioninference today. Composer treatsphpandphp-64bitas constraints on the same version, and takes the highest lower bound across both (AutoloadGenerator::getPlatformCheck()again).ComposerPhpVersionParser::parse()now takes a list of constraints and intersects them withMultiConstraint::create($constraints, true), whose conjunctive bounds are the max of the lower bounds and the min of the upper bounds.{"require": {"php": "^8.1", "php-64bit": "^8.3"}}gives
int<80300, 80599>rather thanint<80100, 80599>.That change rides on the same toggle. It narrows the version range for projects declaring only
php-64bit, which can flip aPHP_VERSION_ID >= Xcheck toidentical.alwaysTrue, so it carries the same upgrade risk as the int width.Notes
ConfiguredPhpIntSizeHelpermirrorsConfiguredPhpVersionRangeHelper: NEON parameter first, composer.json second,nulllast.phpIntSizeis not inparametersNotInvalidatingCache, so the result cache invalidates on its own.#[AutowiredService]to a new class meanscomposer dump-autoloadbefore running anything locally.Tests
PhpIntSize8Testrunsdata/php-int-size-8.phpwithphpIntSize: 8, gated onPHP_INT_SIZE === 8because the expected values depend on the host's integer width. It assertsPHP_INT_MAX + 1is a float.ConfiguredPhpIntSizeHelperTestandComposerPhpVersionFactoryTestcover the composer.json fixtures with the toggle on and off.