code: private IQ enforceSignature(IQ iq, ImmutableList<Variable> signature) {
  
          ImmutableList<Variable> projectedVariables = iq.getProjectionAtom().getArguments();
  
          if (projectedVariables.equals(signature))
              return iq;
  
          if (projectedVariables.size() != signature.size())
              throw new IllegalArgumentException("The arity of the signature does not match the iq");
  
          InjectiveVar2VarSubstitution renamingSubstitution = substitutionFactory.getInjectiveVar2VarSubstitution(
                  IntStream.range(0, projectedVariables.size())
                          .boxed()
                          .map(i -> Maps.immutableEntry(projectedVariables.get(i), signature.get(i)))
                          .filter(e -> !e.getKey().equals(e.getValue()))
                          .collect(ImmutableCollectors.toMap()));
  
          return queryTransformerFactory.createRenamer(renamingSubstitution)
                  .transform(iq);
      }
docs: Hacked logic: because of ORDER conditions that are expected to use signature variables,
  this method DOES NOT look for conflicts between signature variables and variables only appearing in the sub-tree.
  
  See the history for a better logic breaking this ugly hack.
  
  TODO: after getting rid of Datalog for encoding SPARQL queries, could try to clean it