Skip to content

Commit 3ea1fb4

Browse files
VincentLangletondrejmirtes
authored andcommitted
Do not infer anything when context is falsy
1 parent 734f645 commit 3ea1fb4

File tree

4 files changed

+51
-13
lines changed

4 files changed

+51
-13
lines changed

src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
use PHPStan\Analyser\TypeSpecifierContext;
1111
use PHPStan\Reflection\FunctionReflection;
1212
use PHPStan\Type\Constant\ConstantBooleanType;
13-
use PHPStan\Type\Constant\ConstantStringType;
1413
use PHPStan\Type\FunctionTypeSpecifyingExtension;
1514
use function count;
1615
use function strtolower;
@@ -34,18 +33,15 @@ public function isFunctionSupported(FunctionReflection $functionReflection, Func
3433

3534
public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes
3635
{
37-
if (count($node->getArgs()) < 2) {
36+
if (!$context->truthy() || count($node->getArgs()) < 2) {
3837
return new SpecifiedTypes();
3938
}
39+
4040
$objectOrClassType = $scope->getType($node->getArgs()[0]->value);
4141
$classType = $scope->getType($node->getArgs()[1]->value);
4242
$allowStringType = isset($node->getArgs()[2]) ? $scope->getType($node->getArgs()[2]->value) : new ConstantBooleanType(true);
4343
$allowString = !$allowStringType->equals(new ConstantBooleanType(false));
4444

45-
if (!$classType instanceof ConstantStringType && !$context->truthy()) {
46-
return new SpecifiedTypes([], []);
47-
}
48-
4945
return $this->typeSpecifier->create(
5046
$node->getArgs()[0]->value,
5147
$this->isAFunctionTypeSpecifyingHelper->determineType($objectOrClassType, $classType, $allowString, false),

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,7 @@ public function dataFileAsserts(): iterable
822822
yield from $this->gatherAssertTypes(__DIR__ . '/data/array-search-type-specifying.php');
823823
yield from $this->gatherAssertTypes(__DIR__ . '/data/array-replace.php');
824824
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-6889.php');
825+
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-6891.php');
825826
yield from $this->gatherAssertTypes(__DIR__ . '/data/simplexml.php');
826827
}
827828

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug6891;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class HelloWorld
8+
{
9+
10+
/**
11+
* @param mixed $context
12+
*/
13+
public function sayHello($context): bool
14+
{
15+
if (is_subclass_of($context, HelloWorld::class)) {
16+
return true;
17+
}
18+
assertType('mixed', $context);
19+
20+
return HelloWorld::class === $context;
21+
}
22+
23+
public function sayHello2(object $context): bool
24+
{
25+
if (is_subclass_of($context, HelloWorld::class)) {
26+
return true;
27+
}
28+
assertType('object', $context);
29+
30+
return HelloWorld::class === get_class($context);
31+
}
32+
33+
public function sayHello3(string $context): bool
34+
{
35+
if (is_subclass_of($context, HelloWorld::class)) {
36+
return true;
37+
}
38+
assertType('string', $context);
39+
40+
return HelloWorld::class === $context;
41+
}
42+
}

tests/PHPStan/Analyser/data/generic-class-string.php

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,20 @@ function testMixed($a) {
2121
assertType('class-string<DateTimeInterface>|DateTimeInterface', $a);
2222
assertType('DateTimeInterface', new $a());
2323
} else {
24-
assertType('mixed~class-string<DateTimeInterface>|DateTimeInterface', $a);
24+
assertType('mixed', $a);
2525
}
2626

2727
if (is_subclass_of($a, 'DateTimeInterface') || is_subclass_of($a, 'stdClass')) {
2828
assertType('class-string<DateTimeInterface>|class-string<stdClass>|DateTimeInterface|stdClass', $a);
2929
assertType('DateTimeInterface|stdClass', new $a());
3030
} else {
31-
// could also exclude stdClass
32-
assertType('mixed~class-string<DateTimeInterface>|DateTimeInterface', $a);
31+
assertType('mixed', $a);
3332
}
3433

3534
if (is_subclass_of($a, C::class)) {
3635
assertType('int', $a::f());
3736
} else {
38-
assertType('mixed~class-string<PHPStan\Generics\GenericClassStringType\C>|PHPStan\Generics\GenericClassStringType\C', $a);
37+
assertType('mixed', $a);
3938
}
4039
}
4140

@@ -48,7 +47,7 @@ function testObject($a) {
4847
if (is_subclass_of($a, 'DateTimeInterface')) {
4948
assertType('DateTimeInterface', $a);
5049
} else {
51-
assertType('object~DateTimeInterface', $a);
50+
assertType('object', $a);
5251
}
5352
}
5453

@@ -82,13 +81,13 @@ function testStringObject($a) {
8281
assertType('class-string<DateTimeInterface>|DateTimeInterface', $a);
8382
assertType('DateTimeInterface', new $a());
8483
} else {
85-
assertType('object~DateTimeInterface|string', $a);
84+
assertType('object|string', $a);
8685
}
8786

8887
if (is_subclass_of($a, C::class)) {
8988
assertType('int', $a::f());
9089
} else {
91-
assertType('object~PHPStan\Generics\GenericClassStringType\C|string', $a);
90+
assertType('object|string', $a);
9291
}
9392
}
9493

0 commit comments

Comments
 (0)