1919use PHPStan \Reflection \ClassConstantReflection ;
2020use PHPStan \Reflection \ClassMemberAccessAnswerer ;
2121use PHPStan \Reflection \ClassReflection ;
22+ use PHPStan \Reflection \Dummy \DummyPropertyReflection ;
2223use PHPStan \Reflection \ExtendedMethodReflection ;
2324use PHPStan \Reflection \ExtendedPropertyReflection ;
2425use PHPStan \Reflection \Php \UniversalObjectCratesClassReflectionExtension ;
2526use PHPStan \Reflection \PropertyReflection ;
2627use PHPStan \Reflection \ReflectionProviderStaticAccessor ;
2728use PHPStan \Reflection \TrivialParametersAcceptor ;
29+ use PHPStan \Reflection \Type \CallbackUnresolvedPropertyPrototypeReflection ;
2830use PHPStan \Reflection \Type \CalledOnTypeUnresolvedMethodPrototypeReflection ;
2931use PHPStan \Reflection \Type \CalledOnTypeUnresolvedPropertyPrototypeReflection ;
3032use 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 ();
0 commit comments