Skip to content

Commit da248b2

Browse files
rvanvelzenondrejmirtes
authored andcommitted
Retain sort order in intersection type
1 parent a72e39c commit da248b2

2 files changed

Lines changed: 24 additions & 12 deletions

File tree

‎src/Type/IntersectionType.php‎

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
use function count;
3131
use function implode;
3232
use function in_array;
33+
use function ksort;
3334
use function sprintf;
3435
use function strlen;
3536
use function substr;
@@ -206,7 +207,7 @@ private function describeItself(VerbosityLevel $level, bool $skipAccessoryTypes)
206207

207208
$nonEmptyStr = false;
208209
$nonFalsyStr = false;
209-
foreach ($this->getSortedTypes() as $type) {
210+
foreach ($this->getSortedTypes() as $i => $type) {
210211
if ($type instanceof AccessoryNonEmptyStringType
211212
|| $type instanceof AccessoryLiteralStringType
212213
|| $type instanceof AccessoryNumericStringType
@@ -229,43 +230,43 @@ private function describeItself(VerbosityLevel $level, bool $skipAccessoryTypes)
229230
}
230231
}
231232

232-
$typesToDescribe[] = $type;
233+
$typesToDescribe[$i] = $type;
233234
$skipTypeNames[] = 'string';
234235
continue;
235236
}
236237
if ($type instanceof NonEmptyArrayType || $type instanceof AccessoryArrayListType) {
237-
$typesToDescribe[] = $type;
238+
$typesToDescribe[$i] = $type;
238239
$skipTypeNames[] = 'array';
239240
continue;
240241
}
241242

242243
if ($type instanceof CallableType && $type->isCommonCallable()) {
243-
$typesToDescribe[] = $type;
244+
$typesToDescribe[$i] = $type;
244245
$skipTypeNames[] = 'object';
245246
$skipTypeNames[] = 'string';
246247
continue;
247248
}
248249

249250
if (!$type instanceof AccessoryType) {
250-
$baseTypes[] = $type;
251+
$baseTypes[$i] = $type;
251252
continue;
252253
}
253254

254255
if ($skipAccessoryTypes) {
255256
continue;
256257
}
257258

258-
$typesToDescribe[] = $type;
259+
$typesToDescribe[$i] = $type;
259260
}
260261

261262
$describedTypes = [];
262-
foreach ($baseTypes as $type) {
263+
foreach ($baseTypes as $i => $type) {
263264
$typeDescription = $type->describe($level);
264265

265266
if (in_array($typeDescription, ['object', 'string'], true) && in_array($typeDescription, $skipTypeNames, true)) {
266267
foreach ($typesToDescribe as $j => $typeToDescribe) {
267268
if ($typeToDescribe instanceof CallableType && $typeToDescribe->isCommonCallable()) {
268-
$describedTypes[] = 'callable-' . $typeDescription;
269+
$describedTypes[$i] = 'callable-' . $typeDescription;
269270
unset($typesToDescribe[$j]);
270271
continue 2;
271272
}
@@ -298,21 +299,23 @@ private function describeItself(VerbosityLevel $level, bool $skipAccessoryTypes)
298299
$typeName = 'non-empty-' . $typeName;
299300
}
300301

301-
$describedTypes[] = $typeName . '<' . substr($typeDescription, strlen('array<'));
302+
$describedTypes[$i] = $typeName . '<' . substr($typeDescription, strlen('array<'));
302303
continue;
303304
}
304305

305306
if (in_array($typeDescription, $skipTypeNames, true)) {
306307
continue;
307308
}
308309

309-
$describedTypes[] = $type->describe($level);
310+
$describedTypes[$i] = $type->describe($level);
310311
}
311312

312-
foreach ($typesToDescribe as $typeToDescribe) {
313-
$describedTypes[] = $typeToDescribe->describe($level);
313+
foreach ($typesToDescribe as $i => $typeToDescribe) {
314+
$describedTypes[$i] = $typeToDescribe->describe($level);
314315
}
315316

317+
ksort($describedTypes);
318+
316319
return implode('&', $describedTypes);
317320
}
318321

‎tests/PHPStan/Analyser/data/callable-object.php‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace CallableObject;
44

5+
use Iterator;
56
use function PHPStan\Testing\assertType;
67

78
/**
@@ -27,3 +28,11 @@ function foo(callable $callable, $object, $callableObject)
2728
assertType('callable-object', $object);
2829
}
2930
}
31+
32+
/**
33+
* @param Iterator&callable $object
34+
*/
35+
function bar($object)
36+
{
37+
assertType('callable(): mixed&Iterator', $object);
38+
}

0 commit comments

Comments
 (0)