public function equals(LatticeElementInterface $that) { if (!$that instanceof LinkedFlowScope) { return false; } if ($this->optimize() === $that->optimize()) { return true; } // If two flow scopes are in the same function, then they could have two possible function scopes: // 1) the real function scope, or // 2) the BOTTOM scope. // If they have different function scopes, we theoretically should iterate through all the variable in each // scope and compare. However, 99.9% of the time, they're not equal. The other 0.1% of the time, we can just // assume that they are equal. Eventually, it just means that data flow analysis has to propagate the entry // lattice a bit further than it really needs to, but the end result is not affected. if ($this->getFunctionScope() !== $that->getFunctionScope()) { return false; } if ($this->cache === $that->cache) { // If the two flow scopes have the same cache, then we can check equality a lot faster: by just looking at // the "dirty" elements in the cache, and comparing them in both scopes. foreach ($this->cache->dirtySymbols as $name) { if ($this->diffSlots($this->getSlot($name), $that->getSlot($name))) { return false; } } return true; } $myFlowSlots = $this->allFlowSlots(); $otherFlowSlots = $that->allFlowSlots(); foreach ($myFlowSlots as $name => $slot) { if ($this->diffSlots($slot, isset($otherFlowSlots[$name]) ? $otherFlowSlots[$name] : null)) { return false; } unset($otherFlowSlots[$name]); } foreach ($otherFlowSlots as $name => $slot) { if ($this->diffSlots($slot, isset($myFlowSlots[$name]) ? $myFlowSlots[$name] : null)) { return false; } } return true; }