Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions src/Type/Generic/TemplateTypeHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,7 @@
{
if (!$templateType->getVariance()->covariant()) {
$isArrayKey = $templateType->getBound()->describe(VerbosityLevel::precise()) === '(int|string)';
if ($type->isScalar()->yes() && $isArrayKey) {
$type = $type->generalize(GeneralizePrecision::templateArgument());
} elseif ($type->isConstantValue()->yes() && (!$templateType->getBound()->isScalar()->yes() || $isArrayKey)) {
if ($type->isConstantValue()->yes() && ($isArrayKey || !$templateType->getBound()->isScalar()->yes())) {

Check warning on line 145 in src/Type/Generic/TemplateTypeHelper.php

View workflow job for this annotation

GitHub Actions / Mutation Testing (8.3, ubuntu-latest)

Escaped Mutant for Mutator "PHPStan\Infection\TrinaryLogicMutator": @@ @@ { if (!$templateType->getVariance()->covariant()) { $isArrayKey = $templateType->getBound()->describe(VerbosityLevel::precise()) === '(int|string)'; - if ($type->isConstantValue()->yes() && ($isArrayKey || !$templateType->getBound()->isScalar()->yes())) { + if ($type->isConstantValue()->yes() && ($isArrayKey || $templateType->getBound()->isScalar()->no())) { $type = $type->generalize(GeneralizePrecision::templateArgument()); } }

Check warning on line 145 in src/Type/Generic/TemplateTypeHelper.php

View workflow job for this annotation

GitHub Actions / Mutation Testing (8.3, ubuntu-latest)

Escaped Mutant for Mutator "PHPStan\Infection\TrinaryLogicMutator": @@ @@ { if (!$templateType->getVariance()->covariant()) { $isArrayKey = $templateType->getBound()->describe(VerbosityLevel::precise()) === '(int|string)'; - if ($type->isConstantValue()->yes() && ($isArrayKey || !$templateType->getBound()->isScalar()->yes())) { + if (!$type->isConstantValue()->no() && ($isArrayKey || !$templateType->getBound()->isScalar()->yes())) { $type = $type->generalize(GeneralizePrecision::templateArgument()); } }

Check warning on line 145 in src/Type/Generic/TemplateTypeHelper.php

View workflow job for this annotation

GitHub Actions / Mutation Testing (8.4, ubuntu-latest)

Escaped Mutant for Mutator "PHPStan\Infection\TrinaryLogicMutator": @@ @@ { if (!$templateType->getVariance()->covariant()) { $isArrayKey = $templateType->getBound()->describe(VerbosityLevel::precise()) === '(int|string)'; - if ($type->isConstantValue()->yes() && ($isArrayKey || !$templateType->getBound()->isScalar()->yes())) { + if ($type->isConstantValue()->yes() && ($isArrayKey || $templateType->getBound()->isScalar()->no())) { $type = $type->generalize(GeneralizePrecision::templateArgument()); } }

Check warning on line 145 in src/Type/Generic/TemplateTypeHelper.php

View workflow job for this annotation

GitHub Actions / Mutation Testing (8.4, ubuntu-latest)

Escaped Mutant for Mutator "PHPStan\Infection\TrinaryLogicMutator": @@ @@ { if (!$templateType->getVariance()->covariant()) { $isArrayKey = $templateType->getBound()->describe(VerbosityLevel::precise()) === '(int|string)'; - if ($type->isConstantValue()->yes() && ($isArrayKey || !$templateType->getBound()->isScalar()->yes())) { + if (!$type->isConstantValue()->no() && ($isArrayKey || !$templateType->getBound()->isScalar()->yes())) { $type = $type->generalize(GeneralizePrecision::templateArgument()); } }
$type = $type->generalize(GeneralizePrecision::templateArgument());
}
}
Expand Down
40 changes: 40 additions & 0 deletions tests/PHPStan/Analyser/nsrt/bug-12601.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php // lint >= 8.0

declare(strict_types = 1);

namespace Bug12601;

use ArrayIterator;
use IteratorAggregate;
use Traversable;
use function PHPStan\Testing\assertType;

/** @implements IteratorAggregate<non-empty-string, non-empty-string> */
class HelloWorld implements IteratorAggregate
{
/** @param array<non-empty-string, non-empty-string> $map */
public function __construct(private array $map) {}

/** @return Traversable<non-empty-string, non-empty-string> */
public function getIterator(): Traversable
{
$iterator = new ArrayIterator($this->map);
assertType('ArrayIterator<non-empty-string, non-empty-string>', $iterator);
return $iterator;
}
}

/** @implements IteratorAggregate<int<0, max>, non-empty-string> */
class HelloWorld2 implements IteratorAggregate
{
/** @param array<int<0, max>, non-empty-string> $map */
public function __construct(private array $map) {}

/** @return ArrayIterator<int<0, max>, non-empty-string> */
public function getIterator(): Traversable
{
$iterator = new ArrayIterator($this->map);
assertType('ArrayIterator<int<0, max>, non-empty-string>', $iterator);
return $iterator;
}
}
4 changes: 2 additions & 2 deletions tests/PHPStan/Analyser/nsrt/generics-do-not-generalize.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ function (): void {
/** @var list<string> $a */
$a = doFoo();

assertType('ArrayIterator<int, string>', new ArrayIterator($a));
assertType('ArrayIterator<int<0, max>, string>', new ArrayIterator($a));
};

/**
Expand All @@ -115,7 +115,7 @@ function (): void {
/** @var list<string> $a */
$a = doFoo();

assertType('ArrayIterator<int, string>', createArrayIterator($a));
assertType('ArrayIterator<int<0, max>, string>', createArrayIterator($a));
};

/** @template T */
Expand Down
Loading