Skip to content

Commit 818e5e8

Browse files
committed
ensure union and intersection handle single type left correctly
1 parent 590fd36 commit 818e5e8

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

lib/PHPTypes/Type.php

+6-4
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ public function unionWith(Type $otherType) {
203203
$thisSubtypes = $this->type === self::TYPE_UNION ? $this->subTypes : [$this];
204204
$otherSubtypes = $otherType->type === self::TYPE_UNION ? $otherType->subTypes : [$otherType];
205205
$subtypes = self::unique(array_merge($thisSubtypes, $otherSubtypes));
206-
return new self(self::TYPE_UNION, $subtypes);
206+
return count($subtypes) === 1 ? $subtypes[0] : new self(self::TYPE_UNION, $subtypes);
207207
}
208208

209209
/**
@@ -217,7 +217,7 @@ public function intersectionWith(Type $otherType) {
217217
$thisSubtypes = $this->type === self::TYPE_INTERSECTION ? $this->subTypes : [$this];
218218
$otherSubtypes = $otherType->type === self::TYPE_INTERSECTION ? $otherType->subTypes : [$otherType];
219219
$subtypes = self::unique(array_merge($thisSubtypes, $otherSubtypes));
220-
return new self(self::TYPE_INTERSECTION, $subtypes);
220+
return count($subtypes) === 1 ? $subtypes[0] : new self(self::TYPE_INTERSECTION, $subtypes);
221221
}
222222

223223
/**
@@ -355,9 +355,10 @@ public static function getPrimitives() {
355355
* @return Type|null
356356
*/
357357
public static function union($types) {
358+
/** @var Type|null $result */
358359
$result = null;
359360
foreach ($types as $type) {
360-
$result = $result === null ? $type : $type->unionWith($result);
361+
$result = $result === null ? $type : $result->unionWith($type);
361362
}
362363
return $result;
363364
}
@@ -367,9 +368,10 @@ public static function union($types) {
367368
* @return Type|null
368369
*/
369370
public static function intersection($types) {
371+
/** @var Type|null $result */
370372
$result = null;
371373
foreach ($types as $type) {
372-
$result = $result === null ? $type : $type->intersectionWith($result);
374+
$result = $result === null ? $type : $result->intersectionWith($type);
373375
}
374376
return $result;
375377
}

test/PHPTypes/TypeTest.php

+29
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,33 @@ public function testDecl($decl, $result) {
3434
$this->assertEquals($decl, (string) $type);
3535
}
3636

37+
public function provideTestUnion() {
38+
return [
39+
[[new Type(Type::TYPE_LONG), new Type(Type::TYPE_STRING)], new Type(Type::TYPE_UNION, [new Type(Type::TYPE_LONG), new Type(Type::TYPE_STRING)])],
40+
[[new Type(Type::TYPE_LONG), new Type(Type::TYPE_LONG)], new Type(Type::TYPE_LONG)],
41+
];
42+
}
43+
44+
/**
45+
* @dataProvider provideTestUnion
46+
*/
47+
public function testUnion($types, $expected) {
48+
$type = Type::union($types);
49+
$this->assertEquals($expected, $type);
50+
}
51+
52+
public function provideTestIntersection() {
53+
return [
54+
[[new Type(Type::TYPE_LONG), new Type(Type::TYPE_STRING)], new Type(Type::TYPE_INTERSECTION, [new Type(Type::TYPE_LONG), new Type(Type::TYPE_STRING)])],
55+
[[new Type(Type::TYPE_LONG), new Type(Type::TYPE_LONG)], new Type(Type::TYPE_LONG)],
56+
];
57+
}
58+
59+
/**
60+
* @dataProvider provideTestIntersection
61+
*/
62+
public function testIntersection($types, $expected) {
63+
$type = Type::intersection($types);
64+
$this->assertEquals($expected, $type);
65+
}
3766
}

0 commit comments

Comments
 (0)