Skip to content

Commit

Permalink
Fix static magic method pureness not being inherited from traits
Browse files Browse the repository at this point in the history
vimeo#10385 "broke" this by propagating pseudo static methods from traits to using classes.
`AtomicStaticCallAnalyzer` was then not capable of dealing with this, because now these static pseudo methods actually exist.

It seems the logic in `AtomicStaticCallAnalyzer` should've been using `::getDeclaringMethodId()` instead of `::getAppearingMethodId()` for this purpose anyway, at least as long as the methods from traits aren't actually transferred to the using class.
  • Loading branch information
tscni committed Nov 29, 2023
1 parent 982f95c commit 7705d92
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -566,12 +566,12 @@ private static function handleNamedCall(
true,
$context->insideUse(),
)) {
$callstatic_appearing_id = $codebase->methods->getAppearingMethodId($callstatic_id);
assert($callstatic_appearing_id !== null);
$callstatic_declaring_id = $codebase->methods->getDeclaringMethodId($callstatic_id);
assert($callstatic_declaring_id !== null);
$callstatic_pure = false;
$callstatic_mutation_free = false;
if ($codebase->methods->hasStorage($callstatic_appearing_id)) {
$callstatic_storage = $codebase->methods->getStorage($callstatic_appearing_id);
if ($codebase->methods->hasStorage($callstatic_declaring_id)) {
$callstatic_storage = $codebase->methods->getStorage($callstatic_declaring_id);
$callstatic_pure = $callstatic_storage->pure;
$callstatic_mutation_free = $callstatic_storage->mutation_free;
}
Expand Down
75 changes: 75 additions & 0 deletions tests/PureAnnotationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,81 @@ function gimmeFoo(): MyEnum
return MyEnum::FOO();
}',
],
'pureThroughCallStaticInTrait' => [
'code' => '<?php
/**
* @method static static foo()
*/
trait TestTrait {
/** @psalm-pure */
public static function __callStatic(string $name, array $params): static
{
throw new BadMethodCallException("not implemented");
}
}
class Test {
use TestTrait;
}
/** @psalm-pure */
function gimmeFoo(): Test
{
return Test::foo();
}',
],
'pureThroughCallStaticInNestedTrait' => [
'code' => '<?php
/**
* @method static static foo()
*/
trait InnerTestTrait {
/** @psalm-pure */
public static function __callStatic(string $name, array $params): static
{
throw new BadMethodCallException("not implemented");
}
}
trait TestTrait {
use InnerTestTrait;
}
class Test {
use TestTrait;
}
/** @psalm-pure */
function gimmeFoo(): Test
{
return Test::foo();
}',
],
'pureThroughAliasedCallStaticInTrait' => [
'code' => '<?php
/**
* @method static static foo()
*/
trait TestTrait {
/** @psalm-pure */
public static function toBeCallStatic(string $name, array $params): static
{
throw new BadMethodCallException("not implemented");
}
}
class Test {
use TestTrait {
TestTrait::toBeCallStatic as __callStatic;
}
}
/** @psalm-pure */
function gimmeFoo(): Test
{
return Test::foo();
}',
],
'dontCrashWhileCheckingPurityOnCallStaticInATrait' => [
'code' => '<?php
/**
Expand Down

0 comments on commit 7705d92

Please sign in to comment.