Skip to content

Commit

Permalink
Do not consider isset checks on static properties as redundant (#5525)
Browse files Browse the repository at this point in the history
* Do not consider isset checks on static properties as redundant

Unlike normal properties, static properties do not have a prescribed
initialization sequence, so they can always be uninitialized (or unset).
Thus `isset()` checks on them are never redundant.

Fixes #5489

* Fix issue with nullable is_static
  • Loading branch information
weirdan authored and muglug committed Apr 25, 2021
1 parent 85a0ef0 commit 933822e
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/Psalm/Internal/Analyzer/ClassAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -802,13 +802,15 @@ public static function addContextProperties(
) {
$property_type->initialized = false;
$property_type->from_property = true;
$property_type->from_static_property = $property_storage->is_static === true;
}
} else {
$property_type = Type::getMixed();

if (!$property_storage->has_default && !$property_storage->is_promoted) {
$property_type->initialized = false;
$property_type->from_property = true;
$property_type->from_static_property = $property_storage->is_static === true;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ public static function analyze(
if ($assign_value_type) {
$assign_value_type = clone $assign_value_type;
$assign_value_type->from_property = false;
$assign_value_type->from_static_property = false;
$assign_value_type->ignore_isset = false;
} else {
$assign_value_type = Type::getMixed();
Expand Down
1 change: 1 addition & 0 deletions src/Psalm/Internal/Type/NegatedAssertionReconciler.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public static function reconcile(
&& $key
&& strpos($key, '[') === false
&& $key !== '$_SESSION'
&& !$existing_var_type->from_static_property
) {
foreach ($existing_var_type->getAtomicTypes() as $atomic) {
if (!$existing_var_type->hasMixed()
Expand Down
2 changes: 2 additions & 0 deletions src/Psalm/Internal/Type/SimpleAssertionReconciler.php
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ private static function reconcileIsset(
&& (!$did_remove_type || empty($existing_var_type->getAtomicTypes()))
&& $key
&& $code_location
&& !$existing_var_type->from_static_property
) {
self::triggerIssueForImpossible(
$existing_var_type,
Expand All @@ -458,6 +459,7 @@ private static function reconcileIsset(
}

$existing_var_type->from_property = false;
$existing_var_type->from_static_property = false;
$existing_var_type->possibly_undefined = false;
$existing_var_type->possibly_undefined_from_try = false;
$existing_var_type->ignore_isset = false;
Expand Down
1 change: 1 addition & 0 deletions src/Psalm/Internal/Type/TypeExpander.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public static function expandUnion(
$fleshed_out_type->by_ref = $return_type->by_ref;
$fleshed_out_type->initialized = $return_type->initialized;
$fleshed_out_type->from_property = $return_type->from_property;
$fleshed_out_type->from_static_property = $return_type->from_static_property;
$fleshed_out_type->had_template = $return_type->had_template;
$fleshed_out_type->parent_nodes = $return_type->parent_nodes;

Expand Down
10 changes: 10 additions & 0 deletions src/Psalm/Type/Union.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ class Union implements TypeNode
*/
public $from_property = false;

/**
* Whether the type originated from *static* property
*
* Unlike non-static properties, static properties have no prescribed place
* like __construct() to be initialized in
*
* @var bool
*/
public $from_static_property = false;

/**
* Whether the property that this type has been derived from has been initialized in a constructor
*
Expand Down
28 changes: 28 additions & 0 deletions tests/TypeReconciliation/IssetTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1006,6 +1006,34 @@ function foo(array $test) : void {
echo $test[0];
}'
],
'issetOnStaticProperty' => [
'<?php
class Singleton {
private static self $instance;
public function getInstance(): self {
if (isset(self::$instance)) {
return self::$instance;
}
return self::$instance = new self();
}
private function __construct() {}
}
',
],
'negatedIssetOnStaticProperty' => [
'<?php
class Singleton {
private static self $instance;
public function getInstance(): self {
if (!isset(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {}
}
',
],
];
}

Expand Down

0 comments on commit 933822e

Please sign in to comment.