Skip to content

Commit c3babe1

Browse files
committed
Fix internal error when assigning new DatePeriod into property
1 parent b9f5f12 commit c3babe1

File tree

2 files changed

+38
-19
lines changed

2 files changed

+38
-19
lines changed

src/Analyser/MutatingScope.php

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5899,28 +5899,31 @@ private function exactInstantiation(New_ $node, string $className): ?Type
58995899

59005900
$assignedToProperty = $node->getAttribute(NewAssignedToPropertyVisitor::ATTRIBUTE_NAME);
59015901
if ($assignedToProperty !== null) {
5902-
$constructorVariant = $constructorMethod->getOnlyVariant();
5903-
$classTemplateTypes = $classReflection->getTemplateTypeMap()->getTypes();
5904-
$originalClassTemplateTypes = $classTemplateTypes;
5905-
foreach ($constructorVariant->getParameters() as $parameter) {
5906-
TypeTraverser::map($parameter->getType(), static function (Type $type, callable $traverse) use (&$classTemplateTypes): Type {
5907-
if ($type instanceof TemplateType && array_key_exists($type->getName(), $classTemplateTypes)) {
5908-
$classTemplateType = $classTemplateTypes[$type->getName()];
5909-
if ($classTemplateType instanceof TemplateType && $classTemplateType->getScope()->equals($type->getScope())) {
5910-
unset($classTemplateTypes[$type->getName()]);
5902+
$constructorVariants = $constructorMethod->getVariants();
5903+
if (count($constructorVariants) === 1) {
5904+
$constructorVariant = $constructorVariants[0];
5905+
$classTemplateTypes = $classReflection->getTemplateTypeMap()->getTypes();
5906+
$originalClassTemplateTypes = $classTemplateTypes;
5907+
foreach ($constructorVariant->getParameters() as $parameter) {
5908+
TypeTraverser::map($parameter->getType(), static function (Type $type, callable $traverse) use (&$classTemplateTypes): Type {
5909+
if ($type instanceof TemplateType && array_key_exists($type->getName(), $classTemplateTypes)) {
5910+
$classTemplateType = $classTemplateTypes[$type->getName()];
5911+
if ($classTemplateType instanceof TemplateType && $classTemplateType->getScope()->equals($type->getScope())) {
5912+
unset($classTemplateTypes[$type->getName()]);
5913+
}
5914+
return $type;
59115915
}
5912-
return $type;
5913-
}
59145916

5915-
return $traverse($type);
5916-
});
5917-
}
5917+
return $traverse($type);
5918+
});
5919+
}
59185920

5919-
if (count($classTemplateTypes) === count($originalClassTemplateTypes)) {
5920-
$propertyType = TypeCombinator::removeNull($this->getType($assignedToProperty));
5921-
$nonFinalObjectType = $isStatic ? new StaticType($nonFinalClassReflection) : new ObjectType($resolvedClassName, classReflection: $nonFinalClassReflection);
5922-
if ($nonFinalObjectType->isSuperTypeOf($propertyType)->yes()) {
5923-
return $propertyType;
5921+
if (count($classTemplateTypes) === count($originalClassTemplateTypes)) {
5922+
$propertyType = TypeCombinator::removeNull($this->getType($assignedToProperty));
5923+
$nonFinalObjectType = $isStatic ? new StaticType($nonFinalClassReflection) : new ObjectType($resolvedClassName, classReflection: $nonFinalClassReflection);
5924+
if ($nonFinalObjectType->isSuperTypeOf($propertyType)->yes()) {
5925+
return $propertyType;
5926+
}
59245927
}
59255928
}
59265929
}

tests/PHPStan/Analyser/nsrt/date-period-return-types.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
<?php declare(strict_types=1);
22

3+
namespace DatePeriodReturnTypes;
4+
5+
use DateInterval;
6+
use DatePeriod;
7+
use DateTime;
8+
use DateTimeImmutable;
39
use function PHPStan\Testing\assertType;
410

511
$start = new DateTime('2012-07-01');
@@ -38,3 +44,13 @@
3844
assertType(\DatePeriod::class, $datePeriod);
3945
assertType(\DateTimeInterface::class . '|null', $datePeriod->getEndDate());
4046
assertType('int|null', $datePeriod->getRecurrences());
47+
48+
class Foo
49+
{
50+
private DatePeriod $period;
51+
52+
public function doFoo(DateTimeImmutable $fromDate, DateTimeImmutable $toDate): void
53+
{
54+
$this->period = new DatePeriod($fromDate, new DateInterval('P1D'), $toDate->modify('+1 day'));
55+
}
56+
}

0 commit comments

Comments
 (0)