Skip to content

Commit 8093c92

Browse files
committed
Leave the existing value checks in place around the shape memos
isSuperTypeOf() records a comparison only after the `no` early return, and getConstantScalarValuesByKey() keeps its original checks and memoizes their outcome, so the lines carrying the pre-existing TrinaryLogic checks are unchanged. Mutation testing had flagged the moved `$typeUnsealedness->yes()` check: `$bothDefinite` rules out the maybe case there, so its `!no()` mutant cannot be told apart. Amp-Thread-ID: https://ampcode.com/threads/T-01a1b24f-e4cc-7457-9324-5d29caf3c481
1 parent bd07af4 commit 8093c92

3 files changed

Lines changed: 45 additions & 36 deletions

File tree

‎src/Type/Constant/ConstantArrayType.php‎

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -840,21 +840,22 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult
840840
? spl_object_id($this->valueTypes[$i]) . ':' . spl_object_id($type->valueTypes[$otherIndex])
841841
: null;
842842
if ($valuePairKey !== null && array_key_exists($valuePairKey, $valueResults)) {
843-
$isValueSuperType = $valueResults[$valuePairKey];
844-
} else {
845-
$otherValueType = $type->getOffsetValueType($keyType);
846-
if ($otherValueType instanceof ErrorType && $bothDefinite && $typeUnsealedness->yes()) {
847-
[, $typeUnsealedValue] = $type->unsealed;
848-
$otherValueType = $typeUnsealedValue;
849-
}
850-
$isValueSuperType = $this->valueTypes[$i]->isSuperTypeOf($otherValueType);
851-
if ($valuePairKey !== null) {
852-
$valueResults[$valuePairKey] = $isValueSuperType;
853-
}
843+
$results[] = $valueResults[$valuePairKey];
844+
continue;
854845
}
846+
847+
$otherValueType = $type->getOffsetValueType($keyType);
848+
if ($otherValueType instanceof ErrorType && $bothDefinite && $typeUnsealedness->yes()) {
849+
[, $typeUnsealedValue] = $type->unsealed;
850+
$otherValueType = $typeUnsealedValue;
851+
}
852+
$isValueSuperType = $this->valueTypes[$i]->isSuperTypeOf($otherValueType);
855853
if ($isValueSuperType->no()) {
856854
return $isValueSuperType->decorateReasons(static fn (string $reason) => sprintf('Offset %s: %s', $keyType->describe(VerbosityLevel::value()), $reason));
857855
}
856+
if ($valuePairKey !== null) {
857+
$valueResults[$valuePairKey] = $isValueSuperType;
858+
}
858859
$results[] = $isValueSuperType;
859860
}
860861

‎src/Type/TypeCombinator.php‎

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1732,19 +1732,22 @@ private static function getConstantScalarValuesByKey(ConstantArrayType $array):
17321732
$singleValues = [];
17331733
foreach ($array->getKeyTypes() as $i => $keyType) {
17341734
$id = spl_object_id($valueTypes[$i]);
1735-
if (!array_key_exists($id, $singleValues)) {
1736-
$singleValues[$id] = null;
1737-
if ($valueTypes[$i]->isConstantScalarValue()->yes()) {
1738-
$constantScalarValues = $valueTypes[$i]->getConstantScalarValues();
1739-
if (count($constantScalarValues) === 1) {
1740-
$singleValues[$id] = [$constantScalarValues[0]];
1741-
}
1735+
if (array_key_exists($id, $singleValues)) {
1736+
if ($singleValues[$id] !== null) {
1737+
$values[$keyType->getValue()] = $singleValues[$id][0];
17421738
}
1739+
continue;
1740+
}
1741+
$singleValues[$id] = null;
1742+
if (!$valueTypes[$i]->isConstantScalarValue()->yes()) {
1743+
continue;
17431744
}
1744-
if ($singleValues[$id] === null) {
1745+
$constantScalarValues = $valueTypes[$i]->getConstantScalarValues();
1746+
if (count($constantScalarValues) !== 1) {
17451747
continue;
17461748
}
1747-
$values[$keyType->getValue()] = $singleValues[$id][0];
1749+
$singleValues[$id] = [$constantScalarValues[0]];
1750+
$values[$keyType->getValue()] = $constantScalarValues[0];
17481751
}
17491752

17501753
return $values;

‎turbo-ext/src/TypeCombinator.cpp‎

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3019,27 +3019,32 @@ class TypeCombinator
30193019
}
30203020
zend_ulong id = (zend_ulong) Z_OBJ_HANDLE_P(valueType);
30213021
zval *single = zend_hash_index_find(singleValues.table(), id);
3022-
if (single == NULL) {
3023-
zv::Val singleValue = zv::Val::null();
3024-
zend_long isConstantScalar = callTrinary(valueType, PT_LC("isconstantscalarvalue"));
3025-
PT_FAIL_IF_NEG(isConstantScalar);
3026-
if (isConstantScalar == PT_TRI_YES) {
3027-
zv::Val constantScalarValues = call(valueType, PT_LC("getconstantscalarvalues"));
3028-
PT_FAIL_IF_UNDEF(constantScalarValues);
3029-
if (countOf(constantScalarValues.raw()) == 1) {
3030-
zv::Arr wrapped = zv::Arr::create(1);
3031-
wrapped.push(zv::Ref(indexOf(constantScalarValues.raw(), 0)));
3032-
singleValue = zv::Val(std::move(wrapped));
3033-
}
3022+
if (single != NULL) {
3023+
if (Z_TYPE_P(single) != IS_NULL) {
3024+
zv::Val keyValue = call(keyEntry.value().raw(), PT_LC("getvalue"));
3025+
PT_FAIL_IF_UNDEF(keyValue);
3026+
zval value;
3027+
ZVAL_COPY(&value, indexOf(single, 0));
3028+
if (UNEXPECTED(!symtableSet(values.table(), keyValue.raw(), &value))) return zv::Val();
30343029
}
3035-
singleValues.arrRef().setIndex(id, zv::Ref(singleValue.raw()));
3036-
single = zend_hash_index_find(singleValues.table(), id);
3030+
continue;
30373031
}
3038-
if (Z_TYPE_P(single) == IS_NULL) continue;
3032+
zval nullZv;
3033+
ZVAL_NULL(&nullZv);
3034+
singleValues.arrRef().setIndex(id, zv::Ref(&nullZv));
3035+
zend_long isConstantScalar = callTrinary(valueType, PT_LC("isconstantscalarvalue"));
3036+
PT_FAIL_IF_NEG(isConstantScalar);
3037+
if (isConstantScalar != PT_TRI_YES) continue;
3038+
zv::Val constantScalarValues = call(valueType, PT_LC("getconstantscalarvalues"));
3039+
PT_FAIL_IF_UNDEF(constantScalarValues);
3040+
if (countOf(constantScalarValues.raw()) != 1) continue;
3041+
zv::Arr wrapped = zv::Arr::create(1);
3042+
wrapped.push(zv::Ref(indexOf(constantScalarValues.raw(), 0)));
3043+
singleValues.arrRef().setIndex(id, zv::Ref(wrapped.raw()));
30393044
zv::Val keyValue = call(keyEntry.value().raw(), PT_LC("getvalue"));
30403045
PT_FAIL_IF_UNDEF(keyValue);
30413046
zval value;
3042-
ZVAL_COPY(&value, indexOf(single, 0));
3047+
ZVAL_COPY(&value, indexOf(constantScalarValues.raw(), 0));
30433048
if (UNEXPECTED(!symtableSet(values.table(), keyValue.raw(), &value))) return zv::Val();
30443049
}
30453050
return zv::Val(std::move(values));

0 commit comments

Comments
 (0)