Skip to content

Commit 51ff531

Browse files
committed
Extract OPTIONAL_KEYS_POWER_SET_LIMIT and FLATTEN_CONSTANT_ARRAYS_LIMIT
1 parent c5d8c7b commit 51ff531

4 files changed

Lines changed: 16 additions & 8 deletions

File tree

‎src/Type/Constant/ConstantArrayType.php‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ class ConstantArrayType implements Type
118118
private const DESCRIBE_LIMIT = 8;
119119
private const CHUNK_FINITE_TYPES_LIMIT = 5;
120120
private const UNSEALED_ARRAY_SHAPES_LINK = 'https://phpstan.org/blog/phpstan-2-2-unsealed-array-shapes-safer-array-keys';
121+
private const OPTIONAL_KEYS_POWER_SET_LIMIT = 10;
121122

122123
private TrinaryLogic $isList;
123124

@@ -389,7 +390,7 @@ public function getAllArrays(): array
389390
return $this->allArrays;
390391
}
391392

392-
if (count($this->optionalKeys) <= 10) {
393+
if (count($this->optionalKeys) <= self::OPTIONAL_KEYS_POWER_SET_LIMIT) {
393394
$optionalKeysCombinations = $this->powerSet($this->optionalKeys);
394395
} else {
395396
$optionalKeysCombinations = [

‎src/Type/TypeUtils.php‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
final class TypeUtils
2424
{
2525

26+
private const FLATTEN_CONSTANT_ARRAYS_LIMIT = 16384;
27+
2628
/**
2729
* @return list<ConstantIntegerType>
2830
*/
@@ -159,7 +161,7 @@ public static function flattenTypes(Type $type): array
159161
foreach ($constantArrays as $constantArray) {
160162
$optionalCount = count($constantArray->getOptionalKeys());
161163
$arrayCount = $optionalCount <= 20 ? (1 << $optionalCount) : PHP_INT_MAX;
162-
if ($arrayCount > 16384 || $estimatedCount > 16384 / max($arrayCount, 1)) {
164+
if ($arrayCount > self::FLATTEN_CONSTANT_ARRAYS_LIMIT || $estimatedCount > self::FLATTEN_CONSTANT_ARRAYS_LIMIT / max($arrayCount, 1)) {
163165
$bail = true;
164166
break;
165167
}

‎turbo-ext/src/ConstantArrayType.cpp‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,14 @@ zend_class_entry *pt_ce_constant_array_type = nullptr;
3939
/* AcceptsResult.cpp: new <result class>($trinary, $reasons, $lazyReasons) */
4040
bool pt_result_object_create(zval *out, zend_class_entry *ce, zval *trinary, zval *reasons, zval *lazyReasons);
4141

42-
/* the twin's private constants */
42+
/* the twin's private constants; getAllArrays() enumerates the power set of
43+
* up to OPTIONAL_KEYS_POWER_SET_LIMIT optional keys */
4344
#define PT_CAT_DESCRIBE_LIMIT 8
4445
#define PT_CAT_CHUNK_FINITE_TYPES_LIMIT 5
4546
#define PT_CAT_UNSEALED_ARRAY_SHAPES_LINK "https://phpstan.org/blog/phpstan-2-2-unsealed-array-shapes-safer-array-keys"
46-
/* the twin's inline thresholds: getAllArrays() enumerates the power set of
47-
* up to this many optional keys, generalize() keeps per-offset accessories
48-
* below this many required keys */
4947
#define PT_CAT_POWER_SET_OPTIONAL_KEYS_LIMIT 10
48+
/* the twin's inline threshold: generalize() keeps per-offset accessories
49+
* below this many required keys */
5050
#define PT_CAT_GENERALIZE_OFFSET_ACCESSORIES_LIMIT 32
5151

5252
/* PHP's CASE_LOWER / CASE_UPPER */
@@ -7308,6 +7308,7 @@ PT_MINIT_REGISTRATION(pt_register_constant_array_type)
73087308
cls.privateClassConstantLong("DESCRIBE_LIMIT", PT_CAT_DESCRIBE_LIMIT);
73097309
cls.privateClassConstantLong("CHUNK_FINITE_TYPES_LIMIT", PT_CAT_CHUNK_FINITE_TYPES_LIMIT);
73107310
cls.privateClassConstantString("UNSEALED_ARRAY_SHAPES_LINK", PT_CAT_UNSEALED_ARRAY_SHAPES_LINK);
7311+
cls.privateClassConstantLong("OPTIONAL_KEYS_POWER_SET_LIMIT", PT_CAT_POWER_SET_OPTIONAL_KEYS_LIMIT);
73117312

73127313
cls.method(sigs::__construct, [](INTERNAL_FUNCTION_PARAMETERS) {
73137314
zval *keyTypes, *valueTypes, *nextAutoIndexes = NULL, *optionalKeys = NULL, *isList = NULL, *unsealed = NULL;

‎turbo-ext/src/TypeUtils.cpp‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ namespace sigs = ptdecl::TypeUtils::sig;
2323

2424
zend_class_entry *pt_ce_type_utils = nullptr;
2525

26+
/* the twin's private constant */
27+
#define PT_TU_FLATTEN_CONSTANT_ARRAYS_LIMIT 16384
28+
2629
namespace phpstanturbo {
2730

2831
struct ConstantArrayCombinationContext
@@ -215,7 +218,7 @@ class TypeUtils
215218
* expanding: each ConstantArrayType with N optional keys produces
216219
* 2^N variants from getAllArrays(), multiplied across the
217220
* constant arrays; bail out above the limit rather than allocate
218-
* O(2^N). The twin's `16384 / max($arrayCount, 1)` is a float
221+
* O(2^N). The twin's `FLATTEN_CONSTANT_ARRAYS_LIMIT / max($arrayCount, 1)` is a float
219222
* division — compared as one here. */
220223
zend_long estimatedCount = 1;
221224
bool bail = false;
@@ -233,7 +236,7 @@ class TypeUtils
233236
}
234237
zend_long optionalCount = (zend_long) zv::ArrRef(optionalKeys.raw()).size();
235238
zend_long arrayCount = optionalCount <= 20 ? ((zend_long) 1 << optionalCount) : ZEND_LONG_MAX;
236-
if (arrayCount > 16384 || (double) estimatedCount > 16384.0 / (double) (arrayCount > 1 ? arrayCount : 1)) {
239+
if (arrayCount > PT_TU_FLATTEN_CONSTANT_ARRAYS_LIMIT || (double) estimatedCount > (double) PT_TU_FLATTEN_CONSTANT_ARRAYS_LIMIT / (double) (arrayCount > 1 ? arrayCount : 1)) {
237240
bail = true;
238241
break;
239242
}
@@ -481,6 +484,7 @@ PT_MINIT_REGISTRATION(pt_register_type_utils)
481484
{
482485
reg::Class cls("PHPStan\\Type\\TypeUtils");
483486
ptdecl::TypeUtils::declareClass(cls);
487+
cls.privateClassConstantLong("FLATTEN_CONSTANT_ARRAYS_LIMIT", PT_TU_FLATTEN_CONSTANT_ARRAYS_LIMIT);
484488
ptdecl::TypeUtils::declareProperties(cls);
485489

486490
static const reg::Arg nullableThisType = reg::obj("", "PHPStan\\Type\\ThisType", true);

0 commit comments

Comments
 (0)