code: private IQTree liftBinding(ConstructionNode childConstructionNode, UnaryIQTree liftedChildIQ,
                                 IQProperties currentIQProperties, VariableGenerator variableGenerator) {
          IQTree grandChildIQTree = liftedChildIQ.getChild();
  
          IQProperties liftedProperties = currentIQProperties.declareLifted();
  
          ImmutableExpression unoptimizedExpression = childConstructionNode.getSubstitution()
                  .applyToBooleanExpression(getFilterCondition());
  
          try {
              ExpressionAndSubstitution expressionAndSubstitution = simplifyCondition(Optional.of(unoptimizedExpression),
                      ImmutableSet.of());
  
              Optional<FilterNode> newFilterNode = expressionAndSubstitution.optionalExpression
                      .map(iqFactory::createFilterNode);
  
              if (expressionAndSubstitution.substitution.isEmpty()) {
                  IQTree filterLevelTree = newFilterNode
                          .map(n -> (IQTree) iqFactory.createUnaryIQTree(n, grandChildIQTree, liftedProperties))
                          .orElse(grandChildIQTree);
                  return iqFactory.createUnaryIQTree(childConstructionNode, filterLevelTree, liftedProperties);
              }
              else {
                  IQTree newGrandChild = grandChildIQTree.applyDescendingSubstitution(
                          expressionAndSubstitution.substitution, expressionAndSubstitution.optionalExpression);
  
                  IQTree filterLevelTree = newFilterNode
                          .map(n -> (IQTree) iqFactory.createUnaryIQTree(n, newGrandChild, currentIQProperties))
                          .orElse(newGrandChild);
  
                  IQTree filterParentTree = iqFactory.createUnaryIQTree(
                          iqFactory.createConstructionNode(grandChildIQTree.getVariables(),
                                  (ImmutableSubstitution<ImmutableTerm>)(ImmutableSubstitution<?>)
                                          expressionAndSubstitution.substitution),
                          filterLevelTree);
  
                  // Recursive
                  return iqFactory.createUnaryIQTree(childConstructionNode, filterParentTree, currentIQProperties)
                          .liftBinding(variableGenerator);
              }
  
          } catch (UnsatisfiableConditionException e) {
              return iqFactory.createEmptyNode(childConstructionNode.getVariables());
          }
      }
docs: TODO: let the filter node simplify (interpret) expressions in the lifted substitution