|
35 | 35 | use Throwable; |
36 | 36 | use function array_diff_assoc; |
37 | 37 | use function array_fill_keys; |
| 38 | +use function array_intersect; |
| 39 | +use function array_keys; |
38 | 40 | use function array_map; |
39 | 41 | use function array_merge; |
40 | 42 | use function array_slice; |
@@ -212,14 +214,35 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult |
212 | 214 | break; |
213 | 215 | } |
214 | 216 |
|
| 217 | + $innerAccepts = []; |
215 | 218 | $result = AcceptsResult::createNo(); |
216 | 219 | foreach ($this->getSortedTypes() as $i => $innerType) { |
217 | | - $result = $result->or($innerType->accepts($type, $strictTypes)->decorateReasons(static fn (string $reason) => sprintf('Type #%d from the union: %s', $i + 1, $reason))); |
| 220 | + $innerResult = $innerType->accepts($type, $strictTypes); |
| 221 | + $innerAccepts[$i] = $innerResult; |
| 222 | + $result = $result->or($innerResult->decorateReasons(static fn (string $reason) => sprintf('Type #%d from the union: %s', $i + 1, $reason))); |
218 | 223 | } |
219 | 224 | if ($result->yes()) { |
220 | 225 | return $result; |
221 | 226 | } |
222 | 227 |
|
| 228 | + $commonReasons = null; |
| 229 | + foreach ($innerAccepts as $innerResult) { |
| 230 | + if ($commonReasons === null) { |
| 231 | + $commonReasons = $innerResult->reasons; |
| 232 | + continue; |
| 233 | + } |
| 234 | + $commonReasons = array_values(array_intersect($commonReasons, $innerResult->reasons)); |
| 235 | + } |
| 236 | + if ($commonReasons !== null && count($commonReasons) > 0) { |
| 237 | + $decorated = []; |
| 238 | + foreach (array_keys($innerAccepts) as $i) { |
| 239 | + foreach ($commonReasons as $reason) { |
| 240 | + $decorated[] = sprintf('Type #%d from the union: %s', $i + 1, $reason); |
| 241 | + } |
| 242 | + } |
| 243 | + $result = new AcceptsResult($result->result, $decorated); |
| 244 | + } |
| 245 | + |
223 | 246 | if ($type instanceof CompoundType && !$type instanceof CallableType && !$type instanceof TemplateType && !$type instanceof IntersectionType) { |
224 | 247 | return $type->isAcceptedBy($this, $strictTypes); |
225 | 248 | } |
|
0 commit comments