24
24
use PHPStan \Type \Constant \ConstantStringType ;
25
25
use PHPStan \Type \IterableType ;
26
26
use PHPStan \Type \MixedType ;
27
+ use PHPStan \Type \NeverType ;
27
28
use PHPStan \Type \ObjectType ;
28
29
use PHPStan \Type \StringType ;
29
30
use PHPStan \Type \Type ;
@@ -104,7 +105,7 @@ public static function handleAll(
104
105
reset ($ sureTypes );
105
106
$ exprString = key ($ sureTypes );
106
107
$ 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 {
108
109
return $ sureType [1 ];
109
110
});
110
111
}
@@ -126,7 +127,7 @@ public static function handleAllNot(
126
127
): SpecifiedTypes
127
128
{
128
129
if ($ assertName === 'notNull ' ) {
129
- return self ::arrayOrIterable (
130
+ return self ::allArrayOrIterable (
130
131
$ typeSpecifier ,
131
132
$ scope ,
132
133
$ args [0 ]->value ,
@@ -143,7 +144,7 @@ static function (Type $type): Type {
143
144
}
144
145
145
146
$ objectType = new ObjectType ($ classType ->getValue ());
146
- return self ::arrayOrIterable (
147
+ return self ::allArrayOrIterable (
147
148
$ typeSpecifier ,
148
149
$ scope ,
149
150
$ args [0 ]->value ,
@@ -155,7 +156,7 @@ static function (Type $type) use ($objectType): Type {
155
156
156
157
if ($ assertName === 'notSame ' ) {
157
158
$ valueType = $ scope ->getType ($ args [1 ]->value );
158
- return self ::arrayOrIterable (
159
+ return self ::allArrayOrIterable (
159
160
$ typeSpecifier ,
160
161
$ scope ,
161
162
$ args [0 ]->value ,
@@ -168,7 +169,7 @@ static function (Type $type) use ($valueType): Type {
168
169
throw new ShouldNotHappenException ();
169
170
}
170
171
171
- private static function arrayOrIterable (
172
+ private static function allArrayOrIterable (
172
173
TypeSpecifier $ typeSpecifier ,
173
174
Scope $ scope ,
174
175
Expr $ expr ,
@@ -183,18 +184,30 @@ private static function arrayOrIterable(
183
184
if ($ arrayType instanceof ConstantArrayType) {
184
185
$ builder = ConstantArrayTypeBuilder::createEmpty ();
185
186
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 ));
188
192
}
189
193
$ newArrayTypes [] = $ builder ->getArray ();
190
194
} 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 );
192
200
}
193
201
}
194
202
195
203
$ specifiedType = TypeCombinator::union (...$ newArrayTypes );
196
204
} 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
+ }
198
211
} else {
199
212
return new SpecifiedTypes ([], []);
200
213
}
0 commit comments