Replace the current node with the provided replacement. It's allowed to use a modified version
of this query as the replacement rather than allocating and using a new instance of the query as the replacement.
This will behave like keep() (this node's children will be processed) if the replacement is the same instance as the original node.
It will simply replace and NOT process the children if the replacement is a different instance
(this is to prevent risk of accidental infinite recursion or double-visiting).
If the provided replacement has isEmptyQuery=true, this
node will simply be removed from the query tree instead (just like remove()). This is to prevent accidentaly leaving
an empty "do nothing" query in the tree.