Skip to content
Merged
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
16 changes: 10 additions & 6 deletions src/Analyser/ArgumentsHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
use PHPStan\Node\Expr\NativeTypeExpr;
use PHPStan\Node\InvalidateExprNode;
use PHPStan\Reflection\Callables\SimpleImpurePoint;
use PHPStan\Reflection\Callables\SimpleThrowPoint;
use PHPStan\Reflection\ExtendedMethodReflection;
use PHPStan\Reflection\ExtendedParameterReflection;
use PHPStan\Reflection\FunctionReflection;
Expand Down Expand Up @@ -61,7 +60,6 @@
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\TypeUtils;
use function array_filter;
use function array_keys;
use function array_last;
use function array_map;
Expand Down Expand Up @@ -654,11 +652,17 @@ public function processArgs(
$deferredInvalidateExpressions[] = [$acceptors[0]->getInvalidateExpressions(), $acceptors[0]->getUsedVariables()];
}
if ($callCallbackImmediately) {
$callableThrowPoints = array_map(static fn (SimpleThrowPoint $throwPoint) => $throwPoint->isExplicit() ? InternalThrowPoint::createExplicit($scope, $throwPoint->getType(), $arg->value, $throwPoint->canContainAnyThrowable()) : InternalThrowPoint::createImplicit($scope, $arg->value), $acceptors[0]->getThrowPoints());
if (!$this->implicitThrows) {
$callableThrowPoints = array_values(array_filter($callableThrowPoints, static fn (InternalThrowPoint $throwPoint) => $throwPoint->isExplicit()));
foreach ($acceptors[0]->getThrowPoints() as $throwPoint) {
$isExplicit = $throwPoint->isExplicit();
if (!$this->implicitThrows && !$isExplicit) {
continue;
}
if ($isExplicit) {
$throwPoints[] = InternalThrowPoint::createExplicit($scope, $throwPoint->getType(), $arg->value, $throwPoint->canContainAnyThrowable());
} else {
$throwPoints[] = InternalThrowPoint::createImplicit($scope, $arg->value);
}
}
$throwPoints = array_merge($throwPoints, $callableThrowPoints);
$impurePoints = array_merge($impurePoints, array_map(static fn (SimpleImpurePoint $impurePoint) => new ImpurePoint($scope, $arg->value, $impurePoint->getIdentifier(), $impurePoint->getDescription(), $impurePoint->isCertain()), $acceptors[0]->getImpurePoints()));
}
}
Expand Down
17 changes: 10 additions & 7 deletions src/Analyser/ExprHandler/FuncCallHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
use PHPStan\Parser\ImmediatelyInvokedClosureVisitor;
use PHPStan\Reflection\Callables\CallableParametersAcceptor;
use PHPStan\Reflection\Callables\SimpleImpurePoint;
use PHPStan\Reflection\Callables\SimpleThrowPoint;
use PHPStan\Reflection\ExtendedParametersAcceptor;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Reflection\Native\NativeParameterReflection;
Expand Down Expand Up @@ -85,12 +84,10 @@
use PHPStan\Type\UnionType;
use Throwable;
use WeakReference;
use function array_filter;
use function array_key_first;
use function array_keys;
use function array_map;
use function array_merge;
use function array_values;
use function count;
use function in_array;
use function is_string;
Expand Down Expand Up @@ -194,11 +191,17 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex
) {
// processed later
} elseif ($parametersAcceptor instanceof CallableParametersAcceptor) {
$callableThrowPoints = array_map(static fn (SimpleThrowPoint $throwPoint) => $throwPoint->isExplicit() ? InternalThrowPoint::createExplicit($scope, $throwPoint->getType(), $expr, $throwPoint->canContainAnyThrowable()) : InternalThrowPoint::createImplicit($scope, $expr), $parametersAcceptor->getThrowPoints());
if (!$this->implicitThrows) {
$callableThrowPoints = array_values(array_filter($callableThrowPoints, static fn (InternalThrowPoint $throwPoint) => $throwPoint->isExplicit()));
foreach ($parametersAcceptor->getThrowPoints() as $throwPoint) {
$isExplicit = $throwPoint->isExplicit();
if (!$this->implicitThrows && !$isExplicit) {
continue;
}
if ($isExplicit) {
$throwPoints[] = InternalThrowPoint::createExplicit($scope, $throwPoint->getType(), $expr, $throwPoint->canContainAnyThrowable());
} else {
$throwPoints[] = InternalThrowPoint::createImplicit($scope, $expr);
}
}
$throwPoints = array_merge($throwPoints, $callableThrowPoints);
// A callable value's impure points are resolved from its
// ParametersAcceptor alone, so a conditionally pure function reached
// through a first-class callable arrives here as an unconditional
Expand Down
16 changes: 2 additions & 14 deletions turbo-ext/src/ArgumentsHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2148,11 +2148,11 @@ class ArgumentsHandler
zv::Val simpleThrowPoints = callOn(throwPointsSite, acceptor, PT_LC("getthrowpoints"), "getThrowPoints", 0, NULL);
if (UNEXPECTED(simpleThrowPoints.isUndef() || !requireArray(simpleThrowPoints.raw(), "array_map(): Argument #2 ($array)"))) return false;
zval *scope = w.scope.raw();
zv::Arr callableThrowPoints = zv::Arr::create(zend_hash_num_elements(Z_ARRVAL_P(simpleThrowPoints.raw())));
for (zv::ArrayEntry entry : zv::ArrRef(simpleThrowPoints.raw())) {
zval *throwPoint = entry.value().deref().raw();
zv::Val isExplicit = callOn(pt_ah_simple_throw_point_is_explicit_site, throwPoint, PT_LC("isexplicit"), "isExplicit", 0, NULL);
if (UNEXPECTED(isExplicit.isUndef())) return false;
if (!zend_is_true(slot(slots::implicitThrows)) && !zend_is_true(isExplicit.raw())) continue;
zv::Val mapped;
if (zend_is_true(isExplicit.raw())) {
zv::Val type = callOn(pt_ah_simple_throw_point_get_type_site, throwPoint, PT_LC("gettype"), "getType", 0, NULL);
Expand All @@ -2164,20 +2164,8 @@ class ArgumentsHandler
mapped = pt_internal_throw_point_create_implicit(scope, value);
}
if (UNEXPECTED(mapped.isUndef())) return false;
setKey(callableThrowPoints, entry.stringKeyOrNull(), entry.indexKey(), mapped.raw());
}
if (!zend_is_true(slot(slots::implicitThrows))) {
zv::Arr explicitOnly = zv::Arr::create(zend_hash_num_elements(callableThrowPoints.table()));
for (zv::ArrayEntry entry : zv::TableRef(callableThrowPoints.table())) {
bool isExplicit = false;
if (UNEXPECTED(!pt_internal_throw_point_is_explicit(entry.value().raw(), isExplicit))) return false;
if (isExplicit) {
explicitOnly.push(zv::Ref(entry.value().raw()));
}
}
callableThrowPoints = std::move(explicitOnly);
w.throwPoints.push(std::move(mapped));
}
if (UNEXPECTED(!arrayMerge(w.throwPoints, callableThrowPoints.raw()))) return false;

zv::Val simpleImpurePoints = callOn(impurePointsSite, acceptor, PT_LC("getimpurepoints"), "getImpurePoints", 0, NULL);
if (UNEXPECTED(simpleImpurePoints.isUndef() || !requireArray(simpleImpurePoints.raw(), "array_map(): Argument #2 ($array)"))) return false;
Expand Down
24 changes: 2 additions & 22 deletions turbo-ext/src/FuncCallHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1469,12 +1469,11 @@ class FuncCallHandler
zend_type_error("array_map(): Argument #2 ($array) must be of type array, %s given", zend_zval_value_name(simpleThrowPoints.raw()));
return false;
}
/* array_map() keeps the keys of its one array */
zv::Arr callableThrowPoints = zv::Arr::create(zend_hash_num_elements(Z_ARRVAL_P(simpleThrowPoints.raw())));
for (zv::ArrayEntry entry : zv::ArrRef(simpleThrowPoints.raw())) {
zval *simpleThrowPoint = entry.value().deref().raw();
zv::Val explicitValue = callNoArgs(pt_fch_throw_point_explicit_site, simpleThrowPoint, PT_LC("isexplicit"), "isExplicit");
if (UNEXPECTED(explicitValue.isUndef())) return false;
if (!flag(slots::implicitThrows) && !zend_is_true(explicitValue.raw())) continue;
zv::Val throwPoint;
if (zend_is_true(explicitValue.raw())) {
zv::Val type = callNoArgs(pt_fch_throw_point_type_site, simpleThrowPoint, PT_LC("gettype"), "getType");
Expand All @@ -1486,27 +1485,8 @@ class FuncCallHandler
throwPoint = pt_internal_throw_point_create_implicit(scope.raw(), expr);
}
if (UNEXPECTED(throwPoint.isUndef())) return false;
zend_string *key = entry.stringKeyOrNull();
if (key != NULL) {
callableThrowPoints.set(key, std::move(throwPoint));
} else {
callableThrowPoints.separate();
zval value = throwPoint.take();
zend_hash_index_update(callableThrowPoints.table(), entry.indexKey(), &value);
}
}
zv::Val callableThrowPointsHold = zv::Val(std::move(callableThrowPoints));
if (!flag(slots::implicitThrows)) {
/* array_values(array_filter($callableThrowPoints, static fn (InternalThrowPoint $throwPoint) => $throwPoint->isExplicit())) */
zv::Arr explicitOnly = zv::Arr::create(countOf(callableThrowPointsHold.raw()));
for (zv::ArrayEntry entry : zv::ArrRef(callableThrowPointsHold.raw())) {
bool isExplicit;
if (UNEXPECTED(!pt_internal_throw_point_is_explicit(entry.value().raw(), isExplicit))) return false;
if (isExplicit) explicitOnly.push(entry.value());
}
callableThrowPointsHold = zv::Val(std::move(explicitOnly));
zv::ArrRef(throwPoints.raw()).push(zv::Ref(throwPoint.raw()));
}
if (UNEXPECTED(!arrayMerge(throwPoints, callableThrowPointsHold.raw()))) return false;

zv::Val acceptorImpurePoints = pt_parameters_acceptor_call(parametersAcceptor, PT_PA_GET_IMPURE_POINTS);
if (UNEXPECTED(acceptorImpurePoints.isUndef())) return false;
Expand Down
Loading