Skip to content

Commit bf56dbb

Browse files
herndlmondrejmirtes
authored andcommitted
Improve all* handling
1 parent 974b2fb commit bf56dbb

File tree

2 files changed

+37
-10
lines changed

2 files changed

+37
-10
lines changed

src/Type/BeberleiAssert/AssertHelper.php

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use PHPStan\Type\Constant\ConstantStringType;
2525
use PHPStan\Type\IterableType;
2626
use PHPStan\Type\MixedType;
27+
use PHPStan\Type\NeverType;
2728
use PHPStan\Type\ObjectType;
2829
use PHPStan\Type\StringType;
2930
use PHPStan\Type\Type;
@@ -104,7 +105,7 @@ public static function handleAll(
104105
reset($sureTypes);
105106
$exprString = key($sureTypes);
106107
$sureType = $sureTypes[$exprString];
107-
return self::arrayOrIterable($typeSpecifier, $scope, $sureType[0], static function () use ($sureType): Type {
108+
return self::allArrayOrIterable($typeSpecifier, $scope, $sureType[0], static function () use ($sureType): Type {
108109
return $sureType[1];
109110
});
110111
}
@@ -126,7 +127,7 @@ public static function handleAllNot(
126127
): SpecifiedTypes
127128
{
128129
if ($assertName === 'notNull') {
129-
return self::arrayOrIterable(
130+
return self::allArrayOrIterable(
130131
$typeSpecifier,
131132
$scope,
132133
$args[0]->value,
@@ -143,7 +144,7 @@ static function (Type $type): Type {
143144
}
144145

145146
$objectType = new ObjectType($classType->getValue());
146-
return self::arrayOrIterable(
147+
return self::allArrayOrIterable(
147148
$typeSpecifier,
148149
$scope,
149150
$args[0]->value,
@@ -155,7 +156,7 @@ static function (Type $type) use ($objectType): Type {
155156

156157
if ($assertName === 'notSame') {
157158
$valueType = $scope->getType($args[1]->value);
158-
return self::arrayOrIterable(
159+
return self::allArrayOrIterable(
159160
$typeSpecifier,
160161
$scope,
161162
$args[0]->value,
@@ -168,7 +169,7 @@ static function (Type $type) use ($valueType): Type {
168169
throw new ShouldNotHappenException();
169170
}
170171

171-
private static function arrayOrIterable(
172+
private static function allArrayOrIterable(
172173
TypeSpecifier $typeSpecifier,
173174
Scope $scope,
174175
Expr $expr,
@@ -183,18 +184,30 @@ private static function arrayOrIterable(
183184
if ($arrayType instanceof ConstantArrayType) {
184185
$builder = ConstantArrayTypeBuilder::createEmpty();
185186
foreach ($arrayType->getKeyTypes() as $i => $keyType) {
186-
$valueType = $arrayType->getValueTypes()[$i];
187-
$builder->setOffsetValueType($keyType, $typeCallback($valueType), $arrayType->isOptionalKey($i));
187+
$valueType = $typeCallback($arrayType->getValueTypes()[$i]);
188+
if ($valueType instanceof NeverType) {
189+
continue 2;
190+
}
191+
$builder->setOffsetValueType($keyType, $valueType, $arrayType->isOptionalKey($i));
188192
}
189193
$newArrayTypes[] = $builder->getArray();
190194
} else {
191-
$newArrayTypes[] = new ArrayType($arrayType->getKeyType(), $typeCallback($arrayType->getItemType()));
195+
$itemType = $typeCallback($arrayType->getItemType());
196+
if ($itemType instanceof NeverType) {
197+
continue;
198+
}
199+
$newArrayTypes[] = new ArrayType($arrayType->getKeyType(), $itemType);
192200
}
193201
}
194202

195203
$specifiedType = TypeCombinator::union(...$newArrayTypes);
196204
} elseif ((new IterableType(new MixedType(), new MixedType()))->isSuperTypeOf($currentType)->yes()) {
197-
$specifiedType = new IterableType($currentType->getIterableKeyType(), $typeCallback($currentType->getIterableValueType()));
205+
$itemType = $typeCallback($currentType->getIterableValueType());
206+
if ($itemType instanceof NeverType) {
207+
$specifiedType = $itemType;
208+
} else {
209+
$specifiedType = new IterableType($currentType->getIterableKeyType(), $itemType);
210+
}
198211
} else {
199212
return new SpecifiedTypes([], []);
200213
}

tests/Type/BeberleiAssert/data/data.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,16 @@ public function doFoo($a, $b, array $c, iterable $d, $e, $f, $g, $h, $i, $j, $k,
8383
Assertion::allNotNull($w);
8484
\PHPStan\Testing\assertType('array<int>', $w);
8585

86+
/** @var null[] $w */
87+
$w = doFoo();
88+
Assertion::allNotNull($w);
89+
\PHPStan\Testing\assertType('*NEVER*', $w);
90+
91+
/** @var iterable<null> $w */
92+
$w = doFoo();
93+
Assertion::allNotNull($w);
94+
\PHPStan\Testing\assertType('*NEVER*', $w);
95+
8696
/** @var array{baz: float|null}|array{foo?: string|null, bar: int|null} $w */
8797
$w = doFoo();
8898
Assertion::allNotNull($w);
@@ -106,7 +116,11 @@ public function doFoo($a, $b, array $c, iterable $d, $e, $f, $g, $h, $i, $j, $k,
106116
$z = [-1, -2, -3];
107117
}
108118
Assertion::allNotSame($z, -1);
109-
\PHPStan\Testing\assertType('array{*NEVER*, -2, -3}|array{1, 2, 3}', $z);
119+
\PHPStan\Testing\assertType('array{1, 2, 3}', $z);
120+
121+
$z = [-1, -2, -3];
122+
Assertion::allNotSame($z, -1);
123+
\PHPStan\Testing\assertType('*NEVER*', $z);
110124

111125
Assertion::subclassOf($aa, self::class);
112126
\PHPStan\Testing\assertType('class-string<PHPStan\Type\BeberleiAssert\Foo>|PHPStan\Type\BeberleiAssert\Foo', $aa);

0 commit comments

Comments
 (0)