private function doRemove($object, array &$visited): void
    {
        $oid = spl_object_hash($object);
        if (isset($visited[$oid])) {
            return;
        }

        $visited[$oid] = true;

        // Cascade first to avoid problems with proxy initializing out of the identity map.
        $this->cascadeRemove($object, $visited);

        $class = $this->manager->getClassMetadata(get_class($object));
        $documentState = $this->getDocumentState($object);

        switch ($documentState) {
            case self::STATE_NEW:
            case self::STATE_REMOVED:
                // Nothing to do.
                break;

            case self::STATE_MANAGED:
                $this->lifecycleEventManager->preRemove($class, $object);
                $this->scheduleForDeletion($object);
                break;

            case self::STATE_DETACHED:
                throw new \InvalidArgumentException('Detached document cannot be removed');
            default:
                throw new \InvalidArgumentException('Unexpected document state '.$documentState);
        }
    }