Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Turbo/TurboExtensionEnabler.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
final class TurboExtensionEnabler
{

public const EXPECTED_EXTENSION_VERSION = '0d41107';
public const EXPECTED_EXTENSION_VERSION = 'd9d1da6';

private static bool $active = false;

Expand Down
10 changes: 5 additions & 5 deletions src/Type/Constant/ConstantArrayType.php
Original file line number Diff line number Diff line change
Expand Up @@ -718,13 +718,13 @@ private function checkOurKeys(Type $type, bool $strictTypes): AcceptsResult

$result = $result->and($hasOffset);
$otherValueType = $type->getOffsetValueType($keyType);
$verbosity = VerbosityLevel::getRecommendedLevelByType($valueType, $otherValueType);
$verbosity = static fn (): VerbosityLevel => VerbosityLevel::getRecommendedLevelByType($valueType, $otherValueType);
$acceptsValue = $valueType->accepts($otherValueType, $strictTypes)->decorateReasons(
static fn (string $reason) => sprintf(
'Offset %s (%s) does not accept type %s: %s',
$keyType->describe(VerbosityLevel::precise()),
$valueType->describe($verbosity),
$otherValueType->describe($verbosity),
$valueType->describe($verbosity()),
$otherValueType->describe($verbosity()),
$reason,
),
);
Expand All @@ -733,8 +733,8 @@ private function checkOurKeys(Type $type, bool $strictTypes): AcceptsResult
sprintf(
'Offset %s (%s) does not accept type %s.',
$keyType->describe(VerbosityLevel::precise()),
$valueType->describe($verbosity),
$otherValueType->describe($verbosity),
$valueType->describe($verbosity()),
$otherValueType->describe($verbosity()),
),
]);
}
Expand Down
28 changes: 28 additions & 0 deletions tests/bench/data/nested-array-shape-accepts.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php declare(strict_types = 1);

namespace BenchNestedArrayShapeAccepts;

/**
* Passing an array shape on to a parameter of the same shape checks every key, including the
* keys that refer to the nested shape.
*
* @phpstan-type Value = 'a'|'b'|'c'|'d'|string
* @phpstan-type Inner = array{p0?: Value, p1?: Value, p2?: Value, p3?: Value, p4?: Value, p5?: Value, p6?: Value, p7?: Value, p8?: Value, p9?: Value, p10?: Value, p11?: Value, p12?: Value, p13?: Value, p14?: Value, p15?: Value, p16?: Value, p17?: Value, p18?: Value, p19?: Value, p20?: Value, p21?: Value, p22?: Value, p23?: Value, p24?: Value, p25?: Value, p26?: Value, p27?: Value, p28?: Value, p29?: Value, p30?: Value, p31?: Value, p32?: Value, p33?: Value, p34?: Value, p35?: Value, p36?: Value, p37?: Value, p38?: Value, p39?: Value, p40?: Value, p41?: Value, p42?: Value, p43?: Value, p44?: Value, p45?: Value, p46?: Value, p47?: Value, p48?: Value, p49?: Value, p50?: Value, p51?: Value, p52?: Value, p53?: Value, p54?: Value, p55?: Value, p56?: Value, p57?: Value, p58?: Value, p59?: Value, p60?: Value, p61?: Value, p62?: Value, p63?: Value, p64?: Value, p65?: Value, p66?: Value, p67?: Value, p68?: Value, p69?: Value, p70?: Value, p71?: Value, p72?: Value, p73?: Value, p74?: Value, p75?: Value, p76?: Value, p77?: Value, p78?: Value, p79?: Value, p80?: Value, p81?: Value, p82?: Value, p83?: Value, p84?: Value, p85?: Value, p86?: Value, p87?: Value, p88?: Value, p89?: Value, p90?: Value, p91?: Value, p92?: Value, p93?: Value, p94?: Value, p95?: Value, p96?: Value, p97?: Value, p98?: Value, p99?: Value, p100?: Value, p101?: Value, p102?: Value, p103?: Value, p104?: Value, p105?: Value, p106?: Value, p107?: Value, p108?: Value, p109?: Value, p110?: Value, p111?: Value, p112?: Value, p113?: Value, p114?: Value, p115?: Value, p116?: Value, p117?: Value, p118?: Value, p119?: Value, p120?: Value, p121?: Value, p122?: Value, p123?: Value, p124?: Value, p125?: Value, p126?: Value, p127?: Value, p128?: Value, p129?: Value, p130?: Value, p131?: Value, p132?: Value, p133?: Value, p134?: Value, p135?: Value, p136?: Value, p137?: Value, p138?: Value, p139?: Value, p140?: Value, p141?: Value, p142?: Value, p143?: Value, p144?: Value, p145?: Value, p146?: Value, p147?: Value, p148?: Value, p149?: Value}
* @phpstan-type Outer = array{p0?: Value, p1?: Value, p2?: Value, p3?: Value, p4?: Value, p5?: Value, p6?: Value, p7?: Value, p8?: Value, p9?: Value, p10?: Value, p11?: Value, p12?: Value, p13?: Value, p14?: Value, p15?: Value, p16?: Value, p17?: Value, p18?: Value, p19?: Value, p20?: Value, p21?: Value, p22?: Value, p23?: Value, p24?: Value, p25?: Value, p26?: Value, p27?: Value, p28?: Value, p29?: Value, p30?: Value, p31?: Value, p32?: Value, p33?: Value, p34?: Value, p35?: Value, p36?: Value, p37?: Value, p38?: Value, p39?: Value, p40?: Value, p41?: Value, p42?: Value, p43?: Value, p44?: Value, p45?: Value, p46?: Value, p47?: Value, p48?: Value, p49?: Value, p50?: Value, p51?: Value, p52?: Value, p53?: Value, p54?: Value, p55?: Value, p56?: Value, p57?: Value, p58?: Value, p59?: Value, p60?: Value, p61?: Value, p62?: Value, p63?: Value, p64?: Value, p65?: Value, p66?: Value, p67?: Value, p68?: Value, p69?: Value, p70?: Value, p71?: Value, p72?: Value, p73?: Value, p74?: Value, p75?: Value, p76?: Value, p77?: Value, p78?: Value, p79?: Value, p80?: Value, p81?: Value, p82?: Value, p83?: Value, p84?: Value, p85?: Value, p86?: Value, p87?: Value, p88?: Value, p89?: Value, p90?: Value, p91?: Value, p92?: Value, p93?: Value, p94?: Value, p95?: Value, p96?: Value, p97?: Value, p98?: Value, p99?: Value, p100?: Value, p101?: Value, p102?: Value, p103?: Value, p104?: Value, p105?: Value, p106?: Value, p107?: Value, p108?: Value, p109?: Value, p110?: Value, p111?: Value, p112?: Value, p113?: Value, p114?: Value, p115?: Value, p116?: Value, p117?: Value, p118?: Value, p119?: Value, p120?: Value, p121?: Value, p122?: Value, p123?: Value, p124?: Value, p125?: Value, p126?: Value, p127?: Value, p128?: Value, p129?: Value, p130?: Value, p131?: Value, p132?: Value, p133?: Value, p134?: Value, p135?: Value, p136?: Value, p137?: Value, p138?: Value, p139?: Value, p140?: Value, p141?: Value, p142?: Value, p143?: Value, p144?: Value, p145?: Value, p146?: Value, p147?: Value, p148?: Value, p149?: Value, c0?: Inner, c1?: Inner, c2?: Inner, c3?: Inner, c4?: Inner, c5?: Inner, c6?: Inner, c7?: Inner, c8?: Inner, c9?: Inner, c10?: Inner, c11?: Inner, c12?: Inner, c13?: Inner, c14?: Inner, c15?: Inner, c16?: Inner, c17?: Inner, c18?: Inner, c19?: Inner, c20?: Inner, c21?: Inner, c22?: Inner, c23?: Inner, c24?: Inner, c25?: Inner, c26?: Inner, c27?: Inner, c28?: Inner, c29?: Inner, c30?: Inner, c31?: Inner, c32?: Inner, c33?: Inner, c34?: Inner, c35?: Inner, c36?: Inner, c37?: Inner, c38?: Inner, c39?: Inner}
*/
final class Styles
{

/** @param Outer|null $styles */
public function css(?array $styles): string
{
return '';
}

/** @param Outer $styles */
public function classes(array $styles): string
{
return $this->css($styles);
}

}
33 changes: 11 additions & 22 deletions turbo-ext/src/ConstantArrayType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1702,12 +1702,10 @@ class ConstantArrayType
if (UNEXPECTED(result.isUndef())) return zv::Val();
zv::Val otherValueType = callType(Z_OBJ_P(type), PT_LC("getoffsetvaluetype"), 1, keyType);
if (UNEXPECTED(otherValueType.isUndef())) return zv::Val();
zv::Val verbosity = pt_type_verbosity_recommended(valueType, otherValueType.raw());
if (UNEXPECTED(verbosity.isUndef())) return zv::Val();
zv::Args args{otherValueType.raw(), strictTypes};
zv::Val acceptsValue = pt_type_op(Z_OBJ_P(valueType), PT_OP_ACCEPTS, 2, args);
if (UNEXPECTED(acceptsValue.isUndef())) return zv::Val();
zv::Val captured = quadOf(keyType, valueType, verbosity.raw(), otherValueType.raw());
zv::Val captured = tripleOf(keyType, valueType, otherValueType.raw());
acceptsValue = decorateReasons(acceptsValue.raw(), offsetReasonCallback, captured.raw(), NULL);
if (UNEXPECTED(acceptsValue.isUndef())) return zv::Val();
bool reasonless;
Expand All @@ -1716,7 +1714,7 @@ class ConstantArrayType
zend_long typeIsConstantArray = pt_type_op_trinary(Z_OBJ_P(type), PT_OP_IS_CONSTANT_ARRAY, 0, NULL);
if (UNEXPECTED(typeIsConstantArray < 0)) return zv::Val();
if (typeIsConstantArray == PT_TRI_YES) {
acceptsValue = acceptsResultWithReason(acceptsValue.raw(), offsetReason(keyType, valueType, verbosity.raw(), otherValueType.raw(), NULL));
acceptsValue = acceptsResultWithReason(acceptsValue.raw(), offsetReason(keyType, valueType, otherValueType.raw(), NULL));
if (UNEXPECTED(acceptsValue.isUndef())) return zv::Val();
}
}
Expand Down Expand Up @@ -6178,32 +6176,33 @@ class ConstantArrayType
/* the reason of a rejected offset: 'Offset %s (%s) does not accept type
* %s' with the key at the precise level and the value types at the
* recommended one, a trailing reason after ': ' or a full stop */
static zv::Val offsetReason(zval *keyType, zval *valueType, zval *verbosity, zval *otherValueType, zend_string *reason)
static zv::Val offsetReason(zval *keyType, zval *valueType, zval *otherValueType, zend_string *reason)
{
zv::Val keyDescription = describePrecise(keyType);
if (UNEXPECTED(keyDescription.isUndef())) return zv::Val();
zv::Val valueDescription = describeOf(valueType, verbosity);
zv::Val verbosity = pt_type_verbosity_recommended(valueType, otherValueType);
if (UNEXPECTED(verbosity.isUndef())) return zv::Val();
zv::Val valueDescription = describeOf(valueType, verbosity.raw());
if (UNEXPECTED(valueDescription.isUndef())) return zv::Val();
zv::Val otherDescription = describeOf(otherValueType, verbosity);
zv::Val otherDescription = describeOf(otherValueType, verbosity.raw());
if (UNEXPECTED(otherDescription.isUndef())) return zv::Val();
if (reason == NULL) {
return zv::Val::adoptString(zend_strpprintf(0, "Offset %s (%s) does not accept type %s.", ZSTR_VAL(zv::Ref(keyDescription.raw()).asString()), ZSTR_VAL(zv::Ref(valueDescription.raw()).asString()), ZSTR_VAL(zv::Ref(otherDescription.raw()).asString())));
}
return zv::Val::adoptString(zend_strpprintf(0, "Offset %s (%s) does not accept type %s: %s", ZSTR_VAL(zv::Ref(keyDescription.raw()).asString()), ZSTR_VAL(zv::Ref(valueDescription.raw()).asString()), ZSTR_VAL(zv::Ref(otherDescription.raw()).asString()), ZSTR_VAL(reason)));
}

/* checkOurKeys()'s decorator: state0 = [keyType, valueType, verbosity, otherValueType] */
/* checkOurKeys()'s decorator: state0 = [keyType, valueType, otherValueType] */
static void offsetReasonCallback(zval *captured, zval *state1, uint32_t argc, zval *argv, zval *return_value)
{
(void) state1;
zend_string *reason = reasonArgument(argc, argv);
if (UNEXPECTED(reason == NULL || Z_TYPE_P(captured) != IS_ARRAY)) return;
zval *keyType = zend_hash_index_find(Z_ARRVAL_P(captured), 0);
zval *valueType = zend_hash_index_find(Z_ARRVAL_P(captured), 1);
zval *verbosity = zend_hash_index_find(Z_ARRVAL_P(captured), 2);
zval *otherValueType = zend_hash_index_find(Z_ARRVAL_P(captured), 3);
ZEND_ASSERT(keyType != NULL && valueType != NULL && verbosity != NULL && otherValueType != NULL);
zv::Val result = offsetReason(keyType, valueType, verbosity, otherValueType, reason);
zval *otherValueType = zend_hash_index_find(Z_ARRVAL_P(captured), 2);
ZEND_ASSERT(keyType != NULL && valueType != NULL && otherValueType != NULL);
zv::Val result = offsetReason(keyType, valueType, otherValueType, reason);
if (UNEXPECTED(result.isUndef())) return;
result.intoReturnValue(return_value);
}
Expand Down Expand Up @@ -6398,16 +6397,6 @@ class ConstantArrayType
return zv::Val(std::move(triple));
}

static zv::Val quadOf(zval *a, zval *b, zval *c, zval *d)
{
zv::Arr quad = zv::Arr::create(4);
quad.push(zv::Ref(a));
quad.push(zv::Ref(b));
quad.push(zv::Ref(c));
quad.push(zv::Ref(d));
return zv::Val(std::move(quad));
}

/* !$result->yes() && count($result->reasons) === 0; false = pending
* exception */
[[nodiscard]] static bool isNonYesWithoutReasons(zval *result, bool &out)
Expand Down