Skip to content
Permalink
Browse files

Consider intersections when combining generic types

  • Loading branch information...
muglug committed May 8, 2019
1 parent 1db0e38 commit b7529e872b1ec85fa1ded8270fa3345382dc8f64
Showing with 66 additions and 1 deletion.
  1. +28 −1 src/Psalm/Internal/Type/TypeCombination.php
  2. +17 −0 tests/Template/TemplateTest.php
  3. +21 −0 tests/TypeCombinationTest.php
@@ -30,6 +30,7 @@
use Psalm\Type\Atomic\TObject;
use Psalm\Type\Atomic\TScalar;
use Psalm\Type\Atomic\TString;
use Psalm\Type\Atomic\TTemplateParam;
use Psalm\Type\Atomic\TTrue;
use Psalm\Internal\Type\TypeCombination;
use Psalm\Type\Union;
@@ -96,6 +97,11 @@ class TypeCombination
/** @var array<string, Atomic\TLiteralFloat>|null */
private $floats = [];
/**
* @var array<int, TNamedObject|TTemplateParam|TIterable>|null
*/
private $extra_types;
/**
* Combines types together
* - so `int + string = int|string`
@@ -390,11 +396,23 @@ function (Type\Union $type) : bool {
$new_types[] = $array_type;
}
if ($combination->extra_types) {
$combination->extra_types = array_values(
self::combineTypes($combination->extra_types, $codebase)->getTypes()
);
}
foreach ($combination->builtin_type_params as $generic_type => $generic_type_params) {
if ($generic_type === 'iterable') {
$new_types[] = new TIterable($generic_type_params);
} else {
$new_types[] = new TGenericObject($generic_type, $generic_type_params);
$generic_object = new TGenericObject($generic_type, $generic_type_params);
$generic_object->extra_types = $combination->extra_types;
$new_types[] = $generic_object;
if ($combination->named_object_types) {
unset($combination->named_object_types[$generic_type]);
}
}
}
@@ -633,6 +651,15 @@ private static function scrapeTypeProperties(
}
}
if ($type instanceof TNamedObject || $type instanceof TTemplateParam || $type instanceof TIterable) {
if ($type->extra_types) {
$combination->extra_types = array_merge(
$combination->extra_types ?: [],
$type->extra_types
);
}
}
if ($type instanceof TArray && $type_key === 'array') {
foreach ($type->type_params as $i => $type_param) {
if (isset($combination->array_type_params[$i])) {
@@ -2184,6 +2184,23 @@ function ($optional) {
);
}',
],
'reconcileTraversableTemplatedAndNormal' => [
'<?php
function foo(Traversable $t): void {
if ($t instanceof IteratorAggregate) {
$a = $t->getIterator();
$t = $a;
}
if (!$t instanceof Iterator) {
return;
}
if (rand(0, 1) && rand(0, 1)) {
$t->next();
}
}',
],
];
}
@@ -400,6 +400,27 @@ public function providerTestValidTypeCombination()
'Foo<B>',
],
],
'traversableOfMixed' => [
'Traversable<mixed, mixed>',
[
'Traversable',
'Traversable<mixed, mixed>',
],
],
'traversableAndIterator' => [
'Traversable&Iterator',
[
'Traversable&Iterator',
'Traversable&Iterator',
],
],
'traversableOfMixedAndIterator' => [
'Traversable<mixed, mixed>&Iterator',
[
'Traversable<mixed, mixed>&Iterator',
'Traversable<mixed, mixed>&Iterator',
],
],
];
}

0 comments on commit b7529e8

Please sign in to comment.
You can’t perform that action at this time.