Skip to content

Commit 992a666

Browse files
phpstan-botclaude
andcommitted
Extract intersectResultsWithNonObjectGuard() to avoid duplicate has* calls
The non-object guard and intersectResults were calling hasMethod/hasProperty/etc. twice per type. A single-pass private method now computes each result once, checks the guard, and feeds pre-computed results to TrinaryLogic::maxMin. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 65cc372 commit 992a666

1 file changed

Lines changed: 22 additions & 35 deletions

File tree

src/Type/IntersectionType.php

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -552,13 +552,7 @@ public function canAccessProperties(): TrinaryLogic
552552

553553
public function hasProperty(string $propertyName): TrinaryLogic
554554
{
555-
foreach ($this->types as $type) {
556-
if ($type->isObject()->no() && $type->hasProperty($propertyName)->no()) {
557-
return TrinaryLogic::createNo();
558-
}
559-
}
560-
561-
return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->hasProperty($propertyName));
555+
return $this->intersectResultsWithNonObjectGuard(static fn (Type $type): TrinaryLogic => $type->hasProperty($propertyName));
562556
}
563557

564558
public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
@@ -591,13 +585,7 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember
591585

592586
public function hasInstanceProperty(string $propertyName): TrinaryLogic
593587
{
594-
foreach ($this->types as $type) {
595-
if ($type->isObject()->no() && $type->hasInstanceProperty($propertyName)->no()) {
596-
return TrinaryLogic::createNo();
597-
}
598-
}
599-
600-
return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->hasInstanceProperty($propertyName));
588+
return $this->intersectResultsWithNonObjectGuard(static fn (Type $type): TrinaryLogic => $type->hasInstanceProperty($propertyName));
601589
}
602590

603591
public function getInstanceProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
@@ -630,13 +618,7 @@ public function getUnresolvedInstancePropertyPrototype(string $propertyName, Cla
630618

631619
public function hasStaticProperty(string $propertyName): TrinaryLogic
632620
{
633-
foreach ($this->types as $type) {
634-
if ($type->isObject()->no() && $type->hasStaticProperty($propertyName)->no()) {
635-
return TrinaryLogic::createNo();
636-
}
637-
}
638-
639-
return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->hasStaticProperty($propertyName));
621+
return $this->intersectResultsWithNonObjectGuard(static fn (Type $type): TrinaryLogic => $type->hasStaticProperty($propertyName));
640622
}
641623

642624
public function getStaticProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection
@@ -674,13 +656,7 @@ public function canCallMethods(): TrinaryLogic
674656

675657
public function hasMethod(string $methodName): TrinaryLogic
676658
{
677-
foreach ($this->types as $type) {
678-
if ($type->isObject()->no() && $type->hasMethod($methodName)->no()) {
679-
return TrinaryLogic::createNo();
680-
}
681-
}
682-
683-
return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->hasMethod($methodName));
659+
return $this->intersectResultsWithNonObjectGuard(static fn (Type $type): TrinaryLogic => $type->hasMethod($methodName));
684660
}
685661

686662
public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope): ExtendedMethodReflection
@@ -718,13 +694,7 @@ public function canAccessConstants(): TrinaryLogic
718694

719695
public function hasConstant(string $constantName): TrinaryLogic
720696
{
721-
foreach ($this->types as $type) {
722-
if ($type->isObject()->no() && $type->hasConstant($constantName)->no()) {
723-
return TrinaryLogic::createNo();
724-
}
725-
}
726-
727-
return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->hasConstant($constantName));
697+
return $this->intersectResultsWithNonObjectGuard(static fn (Type $type): TrinaryLogic => $type->hasConstant($constantName));
728698
}
729699

730700
public function getConstant(string $constantName): ClassConstantReflection
@@ -1513,6 +1483,23 @@ private function intersectResults(
15131483
return TrinaryLogic::lazyMaxMin($types, $getResult);
15141484
}
15151485

1486+
/**
1487+
* @param callable(Type $type): TrinaryLogic $getResult
1488+
*/
1489+
private function intersectResultsWithNonObjectGuard(callable $getResult): TrinaryLogic
1490+
{
1491+
$results = [];
1492+
foreach ($this->types as $type) {
1493+
$result = $getResult($type);
1494+
if ($type->isObject()->no() && $result->no()) {
1495+
return TrinaryLogic::createNo();
1496+
}
1497+
$results[] = $result;
1498+
}
1499+
1500+
return TrinaryLogic::maxMin(...$results);
1501+
}
1502+
15161503
/**
15171504
* @param callable(Type $type): Type $getType
15181505
*/

0 commit comments

Comments
 (0)