docs: public static <T, U extends Unifiable<? super T>> Choice<Unifier> unifyList(
        Unifier unifier,
        @Nullable List<U> toUnify,
        @Nullable final List<? extends T> targets,
        boolean allowVarargs) {
      if (toUnify == null && targets == null) {
        return Choice.of(unifier);
      } else if (toUnify == null
          || targets == null
          || (allowVarargs
              ? toUnify.size() - 1 > targets.size()
              : toUnify.size() != targets.size())) {
        return Choice.none();
      }
      Choice<Unifier> choice = Choice.of(unifier);
      int index;
      for (index = 0; index < toUnify.size(); index++) {
        U toUnifyNext = toUnify.get(index);
        if (allowVarargs && toUnifyNext instanceof URepeated) {
          final URepeated repeated = (URepeated) toUnifyNext;
          final int startIndex = index;
          return choice
              .condition(index + 1 == toUnify.size())
              .thenOption(
                  new Function<Unifier, Optional<Unifier>>() {
                    @Override
                    public Optional<Unifier> apply(Unifier unifier) {
                      List<JCExpression> expressions = new ArrayList<>();
                      for (int j = startIndex; j < targets.size(); j++) {
                        Optional<Unifier> forked =
                            repeated.unify((JCTree) targets.get(j), unifier.fork()).first();
                        if (!forked.isPresent()) {
                          return Optional.absent();
                        }
                        JCExpression boundExpr = repeated.getUnderlyingBinding(forked.get());
                        if (boundExpr == null) {
                          return Optional.absent();
                        }
                        expressions.add(boundExpr);
                      }
                      unifier.putBinding(repeated.key(), expressions);
                      return Optional.of(unifier);
                    }
                  });
        }
        if (index >= targets.size()) {
          return Choice.none();
        }
        choice = choice.thenChoose(unifications(toUnifyNext, targets.get(index)));
      }
      if (index < targets.size()) {
        return Choice.none();
      }
      return choice;
    }