diff --git a/src/Type/Accessory/AccessoryNonEmptyStringType.php b/src/Type/Accessory/AccessoryNonEmptyStringType.php index 117779e376..dc25ccf544 100644 --- a/src/Type/Accessory/AccessoryNonEmptyStringType.php +++ b/src/Type/Accessory/AccessoryNonEmptyStringType.php @@ -76,6 +76,9 @@ public function accepts(Type $type, bool $strictTypes): TrinaryLogic public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult { + if ($type->isNonEmptyString()->yes()) { + return AcceptsResult::createYes(); + } if ($type instanceof CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } diff --git a/src/Type/IntersectionType.php b/src/Type/IntersectionType.php index f683ad9cbd..52abfdff30 100644 --- a/src/Type/IntersectionType.php +++ b/src/Type/IntersectionType.php @@ -645,6 +645,9 @@ public function isNumericString(): TrinaryLogic public function isNonEmptyString(): TrinaryLogic { + if ($this->isCallable()->yes() && $this->isString()->yes()) { + return TrinaryLogic::createYes(); + } return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->isNonEmptyString()); } diff --git a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php index 3c54d1da2c..d7f49eb912 100644 --- a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php +++ b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php @@ -1481,6 +1481,12 @@ public function testBug11913(): void $this->assertNoErrors($errors); } + public function testBug12979(): void + { + $errors = $this->runAnalyse(__DIR__ . '/data/bug-12979.php'); + $this->assertNoErrors($errors); + } + /** * @param string[]|null $allAnalysedFiles * @return Error[] diff --git a/tests/PHPStan/Analyser/data/bug-12979.php b/tests/PHPStan/Analyser/data/bug-12979.php new file mode 100644 index 0000000000..5cd103b227 --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-12979.php @@ -0,0 +1,21 @@ +acceptNonEmptyString($this->callableString()); + } +}