2424use PHPStan \Reflection \ClassMemberAccessAnswerer ;
2525use PHPStan \Reflection \ClassReflection ;
2626use PHPStan \Reflection \ConstantReflection ;
27+ use PHPStan \Reflection \Dummy \DummyPropertyReflection ;
2728use PHPStan \Reflection \ExtendedMethodReflection ;
2829use PHPStan \Reflection \Php \UniversalObjectCratesClassReflectionExtension ;
2930use PHPStan \Reflection \PropertyReflection ;
3031use PHPStan \Reflection \ReflectionProviderStaticAccessor ;
3132use PHPStan \Reflection \TrivialParametersAcceptor ;
33+ use PHPStan \Reflection \Type \CallbackUnresolvedPropertyPrototypeReflection ;
3234use PHPStan \Reflection \Type \CalledOnTypeUnresolvedMethodPrototypeReflection ;
3335use PHPStan \Reflection \Type \CalledOnTypeUnresolvedPropertyPrototypeReflection ;
3436use PHPStan \Reflection \Type \UnionTypeUnresolvedPropertyPrototypeReflection ;
@@ -159,7 +161,8 @@ public function hasProperty(string $propertyName): TrinaryLogic
159161 return TrinaryLogic::createMaybe ();
160162 }
161163
162- if ($ classReflection ->hasProperty ($ propertyName )) {
164+ $ classHasProperty = RecursionGuard::run ($ this , static fn (): bool => $ classReflection ->hasProperty ($ propertyName ));
165+ if ($ classHasProperty === true || $ classHasProperty instanceof ErrorType) {
163166 return TrinaryLogic::createYes ();
164167 }
165168
@@ -225,7 +228,17 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember
225228 throw new ClassNotFoundException ($ this ->className );
226229 }
227230
228- $ property = $ nakedClassReflection ->getProperty ($ propertyName , $ scope );
231+ $ property = RecursionGuard::run ($ this , static fn () => $ nakedClassReflection ->getProperty ($ propertyName , $ scope ));
232+ if ($ property instanceof ErrorType) {
233+ $ property = new DummyPropertyReflection ();
234+
235+ return new CallbackUnresolvedPropertyPrototypeReflection (
236+ $ property ,
237+ $ property ->getDeclaringClass (),
238+ false ,
239+ static fn (Type $ type ): Type => $ type ,
240+ );
241+ }
229242
230243 $ ancestor = $ this ->getAncestorWithClassName ($ property ->getDeclaringClass ()->getName ());
231244 $ resolvedClassReflection = null ;
@@ -247,6 +260,9 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember
247260 );
248261 }
249262
263+ /**
264+ * @deprecated Not in use anymore.
265+ */
250266 public function getPropertyWithoutTransformingStatic (string $ propertyName , ClassMemberAccessAnswerer $ scope ): PropertyReflection
251267 {
252268 $ classReflection = $ this ->getNakedClassReflection ();
0 commit comments