code: private IQTree updateChild(UnaryIQTree liftedChildTree, ImmutableSubstitution<ImmutableTerm> mergedSubstitution,
                                 ImmutableSet<Variable> projectedVariables) {
          ConstructionNode constructionNode = (ConstructionNode) liftedChildTree.getRootNode();
  
          ConstructionNodeTools.NewSubstitutionPair substitutionPair = constructionTools.traverseConstructionNode(
                  mergedSubstitution, constructionNode.getSubstitution(),
                  constructionNode.getVariables(), projectedVariables);
  
          // NB: this is expected to be ok given that the expected compatibility of the merged substitution with
          // this construction node
          ImmutableSubstitution<? extends VariableOrGroundTerm> descendingSubstitution =
                  substitutionFactory.getSubstitution(
                          (ImmutableMap<Variable, ? extends VariableOrGroundTerm>)(ImmutableMap<Variable, ?>)
                                  substitutionPair.propagatedSubstitution.getImmutableMap());
  
          IQTree newChild = liftedChildTree.getChild()
                  .applyDescendingSubstitution(descendingSubstitution, Optional.empty());
  
          ConstructionNode newConstructionNode = iqFactory.createConstructionNode(projectedVariables,
                      substitutionPair.bindings);
  
          return substitutionPair.bindings.isEmpty()
                  ? newChild
                  : iqFactory.createUnaryIQTree(newConstructionNode, newChild);
      }
docs: TODO: find a better name