code: private ImmutableSubstitution<ImmutableTerm> computeLiftableSubstitution(
              ImmutableSubstitution<? extends ImmutableTerm> selectedSubstitution,
              Optional<Variable> rightProvenanceVariable, ImmutableSet<Variable> leftVariables) {
  
          ImmutableMap<Variable, ImmutableTerm> newMap;
          if (rightProvenanceVariable.isPresent()) {
              newMap = selectedSubstitution.getImmutableMap().entrySet().stream()
                      .filter(e -> !leftVariables.contains(e.getKey()))
                      .collect(ImmutableCollectors.toMap(
                              Map.Entry::getKey,
                              e -> transformRightSubstitutionValue(e.getValue(), leftVariables,
                                      rightProvenanceVariable.get())));
          }
          else {
              newMap = selectedSubstitution.getImmutableMap().entrySet().stream()
                      .filter(e -> !leftVariables.contains(e.getKey()))
                      .collect(ImmutableCollectors.toMap(
                              Map.Entry::getKey,
                              e -> (ImmutableTerm) e.getValue()));
          }
  
          return substitutionFactory.getSubstitution(newMap);
      }
docs: TODO: explain
  
  Right provenance variable: always there if needed
  (when some definitions do not depend on a right-specific variable)