@@ -494,7 +494,8 @@ public function equals(Type $type): bool
494494
495495 public function isCallable (): TrinaryLogic
496496 {
497- $ typeAndMethods = $ this ->findTypeAndMethodNames ();
497+ $ hasNonExistentMethod = false ;
498+ $ typeAndMethods = $ this ->doFindTypeAndMethodNames ($ hasNonExistentMethod );
498499 if ($ typeAndMethods === []) {
499500 return TrinaryLogic::createNo ();
500501 }
@@ -504,7 +505,13 @@ public function isCallable(): TrinaryLogic
504505 $ typeAndMethods ,
505506 );
506507
507- return TrinaryLogic::createYes ()->and (...$ results );
508+ $ result = TrinaryLogic::createYes ()->and (...$ results );
509+
510+ if ($ hasNonExistentMethod ) {
511+ $ result = $ result ->and (TrinaryLogic::createMaybe ());
512+ }
513+
514+ return $ result ;
508515 }
509516
510517 public function getCallableParametersAcceptors (ClassMemberAccessAnswerer $ scope ): array
@@ -537,6 +544,12 @@ public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope)
537544
538545 /** @return ConstantArrayTypeAndMethod[] */
539546 public function findTypeAndMethodNames (): array
547+ {
548+ return $ this ->doFindTypeAndMethodNames ();
549+ }
550+
551+ /** @return ConstantArrayTypeAndMethod[] */
552+ private function doFindTypeAndMethodNames (bool &$ hasNonExistentMethod = false ): array
540553 {
541554 if (count ($ this ->keyTypes ) !== 2 ) {
542555 return [];
@@ -578,6 +591,7 @@ public function findTypeAndMethodNames(): array
578591 foreach ($ methods ->getConstantStrings () as $ methodName ) {
579592 $ has = $ type ->hasMethod ($ methodName ->getValue ());
580593 if ($ has ->no ()) {
594+ $ hasNonExistentMethod = true ;
581595 continue ;
582596 }
583597
0 commit comments