A union of two aliased class names is not deduplicated

The engine rejects a union containing the same type twice, and the check happens at compile time without loading any classes, so two aliases for one class pass.

use VendorMoney as VendorMoney;
use AppMoney;              // suppose these resolve the same

function f(Money|VendorMoney $m) {}   // accepted

function g(int|int $x) {}             // Fatal: duplicate type
function h(int|INT $x) {}             // Fatal — case-insensitive

// and the redundancy check is structural, not semantic:
function i(iterable|array $x) {}      // Fatal, array ⊂ iterable
function j(Countable|Traversable $x) {}  // fine

The deduplication rules read as inconsistent until you know they are all resolved without autoloading: scalar types and the built-in aliases are known to the compiler, and class names are just strings until something instantiates them. The iterable|array rejection catches a genuine mistake and the aliased-class case cannot be caught at all, so an analyser is the only thing that will tell you.