private function extractCommonParentNode(RouteTreeNode $node1, RouteTreeNode $node2): ?RouteTreeNode
    {
        $matcherCompare = static function (SegmentMatcherContract $matcher, SegmentMatcherContract $matcher2) {
            return \strcmp($matcher->getHash(), $matcher2->getHash());
        };

        $commonMatchers = \array_uintersect_assoc($node1->getMatchers(), $node2->getMatchers(), $matcherCompare);

        if (\count($commonMatchers) === 0) {
            return null;
        }

        $children = [];
        $nodes    = [$node1, $node2];

        foreach ($nodes as $node) {
            $specificMatchers  = \array_udiff_assoc($node->getMatchers(), $commonMatchers, $matcherCompare);
            $duplicateMatchers = \array_uintersect_assoc($node->getMatchers(), $commonMatchers, $matcherCompare);

            foreach ($duplicateMatchers as $segmentDepth => $matcher) {
                $commonMatchers[$segmentDepth]->mergeParameterKeys($matcher);
            }

            if (\count($specificMatchers) === 0 && $node->isParentNode()) {
                foreach ($node->getContents()->getChildren() as $childNode) {
                    $children[] = $childNode;
                }
            } else {
                $children[] = $node->update($specificMatchers, $node->getContents());
            }
        }

        return new RouteTreeNode($commonMatchers, new ChildrenNodeCollection($children));
    }