Skip to content

Commit 3a62b4c

Browse files
committed
Merge remote-tracking branch 'origin/1.12.x' into 2.1.x
2 parents b6f87bc + 33c2cb1 commit 3a62b4c

File tree

3 files changed

+49
-2
lines changed

3 files changed

+49
-2
lines changed

src/Type/ObjectType.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@
1919
use PHPStan\Reflection\ClassConstantReflection;
2020
use PHPStan\Reflection\ClassMemberAccessAnswerer;
2121
use PHPStan\Reflection\ClassReflection;
22+
use PHPStan\Reflection\Dummy\DummyPropertyReflection;
2223
use PHPStan\Reflection\ExtendedMethodReflection;
2324
use PHPStan\Reflection\ExtendedPropertyReflection;
2425
use PHPStan\Reflection\Php\UniversalObjectCratesClassReflectionExtension;
2526
use PHPStan\Reflection\PropertyReflection;
2627
use PHPStan\Reflection\ReflectionProviderStaticAccessor;
2728
use PHPStan\Reflection\TrivialParametersAcceptor;
29+
use PHPStan\Reflection\Type\CallbackUnresolvedPropertyPrototypeReflection;
2830
use PHPStan\Reflection\Type\CalledOnTypeUnresolvedMethodPrototypeReflection;
2931
use PHPStan\Reflection\Type\CalledOnTypeUnresolvedPropertyPrototypeReflection;
3032
use PHPStan\Reflection\Type\UnionTypeUnresolvedPropertyPrototypeReflection;
@@ -158,7 +160,8 @@ public function hasProperty(string $propertyName): TrinaryLogic
158160
return TrinaryLogic::createMaybe();
159161
}
160162

161-
if ($classReflection->hasProperty($propertyName)) {
163+
$classHasProperty = RecursionGuard::run($this, static fn (): bool => $classReflection->hasProperty($propertyName));
164+
if ($classHasProperty === true || $classHasProperty instanceof ErrorType) {
162165
return TrinaryLogic::createYes();
163166
}
164167

@@ -224,7 +227,17 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember
224227
throw new ClassNotFoundException($this->className);
225228
}
226229

227-
$property = $nakedClassReflection->getProperty($propertyName, $scope);
230+
$property = RecursionGuard::run($this, static fn () => $nakedClassReflection->getProperty($propertyName, $scope));
231+
if ($property instanceof ErrorType) {
232+
$property = new DummyPropertyReflection();
233+
234+
return new CallbackUnresolvedPropertyPrototypeReflection(
235+
$property,
236+
$property->getDeclaringClass(),
237+
false,
238+
static fn (Type $type): Type => $type,
239+
);
240+
}
228241

229242
$ancestor = $this->getAncestorWithClassName($property->getDeclaringClass()->getName());
230243
$resolvedClassReflection = null;
@@ -246,6 +259,9 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember
246259
);
247260
}
248261

262+
/**
263+
* @deprecated Not in use anymore.
264+
*/
249265
public function getPropertyWithoutTransformingStatic(string $propertyName, ClassMemberAccessAnswerer $scope): PropertyReflection
250266
{
251267
$classReflection = $this->getNakedClassReflection();

tests/PHPStan/Analyser/AnalyserIntegrationTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,12 @@ public function testBug6442(): void
562562
$this->assertSame(9, $errors[1]->getLine());
563563
}
564564

565+
public function testBug13057(): void
566+
{
567+
$errors = $this->runAnalyse(__DIR__ . '/data/bug-13057.php');
568+
$this->assertNoErrors($errors);
569+
}
570+
565571
public function testBug6375(): void
566572
{
567573
$errors = $this->runAnalyse(__DIR__ . '/data/bug-6375.php');
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug13057;
4+
5+
use AllowDynamicProperties;
6+
use function PHPStan\Testing\assertType;
7+
8+
/**
9+
* @property ModelB & object{extra: string} $modelB
10+
*/
11+
#[AllowDynamicProperties]
12+
class ModelA
13+
{}
14+
15+
/**
16+
* @property ModelA & object{extra: string} $modelA
17+
*/
18+
#[AllowDynamicProperties]
19+
class ModelB
20+
{}
21+
22+
function (ModelA $a, ModelB $b): void {
23+
assertType('string', $a->modelB->extra);
24+
assertType('string', $b->modelA->extra);
25+
};

0 commit comments

Comments
 (0)