Skip to content
Permalink
Browse files

Improve performance by doing less cloning

Ref #1837
  • Loading branch information...
muglug committed Jun 26, 2019
1 parent 70a1696 commit c66a106622250d56928cdef90efc0254c3d6c1e8
@@ -301,10 +301,6 @@ public function __construct($self = null)
*/
public function __clone()
{
foreach ($this->vars_in_scope as &$type) {
$type = clone $type;
}
foreach ($this->clauses as &$clause) {
$clause = clone $clause;
}
@@ -353,6 +349,8 @@ public function update(
continue;
}
$existing_type = clone $existing_type;
// if the type changed within the block of statements, process the replacement
// also never allow ourselves to remove all types from a union
if ((!$new_type || !$old_type->equals($new_type))
@@ -366,6 +364,8 @@ public function update(
$updated_vars[$var_id] = true;
}
$this->vars_in_scope[$var_id] = $existing_type;
}
}
}
@@ -1567,6 +1567,9 @@ private function analyzeClassMethod(
);
$method_context = clone $class_context;
foreach ($method_context->vars_in_scope as $context_var_id => $context_type) {
$method_context->vars_in_scope[$context_var_id] = clone $context_type;
}
$method_context->collect_exceptions = $config->check_for_throws_docblock;
$method_analyzer->analyze(
@@ -177,6 +177,10 @@ public static function analyze(
$foreach_context = clone $context;
foreach ($foreach_context->vars_in_scope as $context_var_id => $context_type) {
$foreach_context->vars_in_scope[$context_var_id] = clone $context_type;
}
$foreach_context->inside_loop = true;
$foreach_context->inside_case = false;
@@ -94,6 +94,11 @@ public static function analyze(
if ($assignment_depth === 0 || $has_break_statement) {
$inner_context = clone $loop_scope->loop_context;
foreach ($inner_context->vars_in_scope as $context_var_id => $context_type) {
$inner_context->vars_in_scope[$context_var_id] = clone $context_type;
}
$inner_context->loop_scope = $loop_scope;
$inner_context->parent_context = $loop_scope->loop_context;
@@ -163,6 +168,11 @@ public static function analyze(
$pre_loop_context = clone $loop_scope->loop_context;
$inner_context = clone $loop_scope->loop_context;
foreach ($inner_context->vars_in_scope as $context_var_id => $context_type) {
$inner_context->vars_in_scope[$context_var_id] = clone $context_type;
}
$inner_context->parent_context = $loop_scope->loop_context;
$inner_context->loop_scope = $loop_scope;
@@ -272,7 +272,7 @@ function ($var_id) use ($original_vars_in_scope) {
if ($var_id && isset($pre_op_context->vars_in_scope[$var_id])) {
$left_inferred_reconciled = Reconciler::reconcileTypes(
'!falsy',
$pre_op_context->vars_in_scope[$var_id],
clone $pre_op_context->vars_in_scope[$var_id],
'',
$statements_analyzer,
$context->inside_loop,
@@ -349,6 +349,8 @@ public static function analyze(
) {
$keys_to_remove = [];
$class_type = clone $class_type;
foreach ($class_type->getTypes() as $key => $type) {
if (!$type instanceof TNamedObject) {
$keys_to_remove[] = $key;
@@ -2678,9 +2678,11 @@ private static function coerceValueAfterGatekeeperArgument(
return;
}
if ($param_type->from_docblock && !$input_type->isMixed()) {
if ($param_type->from_docblock && !$input_type->hasMixed()) {
$input_type_changed = false;
$input_type = clone $input_type;
foreach ($param_type->getTypes() as $param_atomic_type) {
if ($param_atomic_type instanceof Type\Atomic\TGenericObject) {
foreach ($input_type->getTypes() as $input_atomic_type) {
@@ -2690,6 +2692,7 @@ private static function coerceValueAfterGatekeeperArgument(
foreach ($input_atomic_type->type_params as $i => $type_param) {
if ($type_param->isEmpty() && isset($param_atomic_type->type_params[$i])) {
$input_type_changed = true;
$input_atomic_type->type_params[$i] = clone $param_atomic_type->type_params[$i];
}
}
@@ -2710,6 +2713,8 @@ private static function coerceValueAfterGatekeeperArgument(
);
if ($var_id) {
$input_type = clone $input_type;
if ($input_type->isNullable() && !$param_type->isNullable()) {
$input_type->removeType('null');
}
@@ -2720,7 +2725,7 @@ private static function coerceValueAfterGatekeeperArgument(
foreach ($input_type->getTypes() as $atomic_type) {
$atomic_type->from_docblock = false;
}
} elseif ($input_type->isMixed() && $signature_param_type) {
} elseif ($input_type->hasMixed() && $signature_param_type) {
$input_type = clone $signature_param_type;
if ($input_type->isNullable()) {
@@ -300,7 +300,7 @@ function (\Psalm\Internal\Clause $c) use ($mixed_var_ids) {
} elseif (isset($stmt->cond->inferredType)) {
$if_return_type_reconciled = Reconciler::reconcileTypes(
'!falsy',
$stmt->cond->inferredType,
clone $stmt->cond->inferredType,
'',
$statements_analyzer,
$context->inside_loop,
@@ -1355,6 +1355,10 @@ public static function combineUnionTypes(
bool $allow_mixed_union = true,
int $literal_limit = 500
) {
if ($type_1 === $type_2) {
return $type_1;
}
if ($type_1->isVanillaMixed() && $type_2->isVanillaMixed()) {
$combined_type = Type::getMixed();
} else {
@@ -1740,6 +1740,24 @@ function getObject() : iterable{
$a = ["1.0", "2.0"];
uksort($a, "version_compare");'
],
'coerceToObjectAfterBeingCalled' => [
'<?php
class Foo {
public function bar() : void {}
}
function takesFoo(Foo $foo) : void {}
/** @param mixed $f */
function takesMixed($f) : void {
if (rand(0, 1)) {
$f = new Foo();
}
/** @psalm-suppress MixedArgument */
takesFoo($f);
$f->bar();
}'
],
];
}

0 comments on commit c66a106

Please sign in to comment.
You can’t perform that action at this time.