diff --git a/stubs/date.stub b/stubs/date.stub index e58c7f0682..8191057c64 100644 --- a/stubs/date.stub +++ b/stubs/date.stub @@ -34,3 +34,19 @@ class DatePeriod implements \IteratorAggregate, \Traversable } } + +interface DateTimeInterface { + /** @return \DateInterval&object{days:int} */ + function diff(\DateTimeInterface $targetObject, bool $absolute = false): \DateInterval + {} +} + +class DateTimeImmutable implements DateTimeInterface { +} + +class DateTime implements DateTimeInterface { +} + +/** @return \DateInterval&object{days:int} */ +function date_diff(\DateTimeInterface $baseObject, \DateTimeInterface $targetObject, bool $absolute = false): \DateInterval +{} diff --git a/tests/PHPStan/Analyser/nsrt/bug-14428.php b/tests/PHPStan/Analyser/nsrt/bug-14428.php new file mode 100644 index 0000000000..f59ce94f3d --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-14428.php @@ -0,0 +1,31 @@ +diff($b); + assertType('int', $interval->days); + doImpure($interval); + assertType('int|false', $interval->days); +} + +function getDateTimeImmutablediff(DateTimeImmutable $a, DateTimeImmutable $b): int { + return $a->diff($b)->days; +} + +function getDatetimediff(DateTime $a, DateTime $b): int { + return $a->diff($b)->days; +} + +function getDateDiffDays(DateTime $a, DateTime $b): int { + return date_diff($a, $b)->days; +} diff --git a/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php b/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php index 0c23f0e6b0..272fc1a39e 100644 --- a/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php @@ -431,4 +431,11 @@ public function testBug13000(): void $this->analyse([__DIR__ . '/data/bug-13000.php'], []); } + public function testBug14428(): void + { + $this->checkNullables = true; + $this->checkExplicitMixed = false; + $this->analyse([__DIR__ . '/../../Analyser/nsrt/bug-14428.php'], []); + } + }