Skip to content

Commit

Permalink
Merge pull request #8586 from Nicelocal/fix_8560
Browse files Browse the repository at this point in the history
Fix #8560
  • Loading branch information
orklah committed Oct 19, 2022
2 parents 0b80db5 + 34a0f2b commit b0970a6
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 4 deletions.
7 changes: 5 additions & 2 deletions src/Psalm/Internal/Type/TypeExpander.php
Expand Up @@ -669,8 +669,10 @@ private static function expandNamedObject(
if (!$final && $return_type instanceof TNamedObject) {
/** @psalm-suppress InaccessibleProperty Acting on a clone */
$return_type->is_static = true;
/** @psalm-suppress InaccessibleProperty Acting on a clone */
$return_type->is_static_resolved = true;
}
} elseif ($return_type->is_static
} elseif ($return_type->is_static && !$return_type->is_static_resolved
&& ($static_class_type instanceof TNamedObject
|| $static_class_type instanceof TTemplateParam)
) {
Expand All @@ -687,7 +689,8 @@ private static function expandNamedObject(
$return_type_types[$extra_static_type->getKey()] = clone $extra_static_type;
}
}
$return_type = $return_type->setIntersectionTypes($return_type_types);
$return_type = $return_type->setIntersectionTypes($return_type_types)
->setIsStatic(true, true);
} elseif ($return_type->is_static && is_string($static_class_type) && $final) {
$return_type = clone $return_type;
/** @psalm-suppress InaccessibleProperty Acting on a clone */
Expand Down
11 changes: 9 additions & 2 deletions src/Psalm/Type/Atomic/TNamedObject.php
Expand Up @@ -31,6 +31,11 @@ class TNamedObject extends Atomic
*/
public $is_static = false;

/**
* @var bool
*/
public $is_static_resolved = false;

/**
* Whether or not this type can represent a child of the class named in $value
* @var bool
Expand Down Expand Up @@ -59,13 +64,15 @@ public function __construct(
$this->from_docblock = $from_docblock;
}

public function setIsStatic(bool $is_static): self
public function setIsStatic(bool $is_static, ?bool $is_static_resolved = null): self
{
if ($this->is_static === $is_static) {
$is_static_resolved ??= $this->is_static_resolved;
if ($this->is_static === $is_static && $this->is_static_resolved === $is_static_resolved) {
return $this;
}
$cloned = clone $this;
$cloned->is_static = $is_static;
$cloned->is_static_resolved = $is_static_resolved;
return $cloned;
}

Expand Down
110 changes: 110 additions & 0 deletions tests/ClassTest.php
Expand Up @@ -611,6 +611,116 @@ function intersect(A $a) {
return $b;
}'
],
'preventDoubleStaticResolution1' => [
'code' => '<?php
/**
* @template TTKey
* @template TTValue
*
* @extends ArrayObject<TTKey, TTValue>
*/
class iter extends ArrayObject {
/**
* @return self<TTKey, TTValue>
*/
public function stabilize(): self {
return $this;
}
}
class a {
/**
* @return iter<int, static>
*/
public function ret(): iter {
return new iter([$this]);
}
}
class b extends a {
}
$a = new b;
$a = $a->ret();
$a = $a->stabilize();',
'assertions' => [
'$a===' => 'iter<int, b&static>'
]
],
'preventDoubleStaticResolution2' => [
'code' => '<?php
/**
* @template TTKey
* @template TTValue
*
* @extends ArrayObject<TTKey, TTValue>
*/
class iter extends ArrayObject {
/**
* @return self<TTKey, TTValue>
*/
public function stabilize(): self {
return $this;
}
}
interface a {
/**
* @return iter<int, static>
*/
public function ret(): iter;
}
class b implements a {
public function ret(): iter {
return new iter([$this]);
}
}
/** @var a */
$a = new b;
$a = $a->ret();
$a = $a->stabilize();',
'assertions' => [
'$a===' => 'iter<int, a&static>'
]
],
'preventDoubleStaticResolution3' => [
'code' => '<?php
/**
* @template TTKey
* @template TTValue
*
* @extends ArrayObject<TTKey, TTValue>
*/
class iter extends ArrayObject {
/**
* @return self<TTKey, TTValue>
*/
public function stabilize(): self {
return $this;
}
}
interface a {
/**
* @return iter<int, a&static>
*/
public function ret(): iter;
}
class b implements a {
public function ret(): iter {
return new iter([$this]);
}
}
/** @var a */
$a = new b;
$a = $a->ret();
$a = $a->stabilize();',
'assertions' => [
'$a===' => 'iter<int, a&static>'
]
],
'allowTraversableImplementationAlongWithIteratorAggregate' => [
'code' => '<?php
/**
Expand Down

0 comments on commit b0970a6

Please sign in to comment.