...in favor of just calling `setException` unconditionally.

I wrote in a code review:

> There's a decent argument that the work we do here and in MoreExecutors.rejectionPropagatingExecutor isn't really buying us much, since it's not clear where else a RejectedExecutionException would be coming from. And even if it is coming from somewhere else, the most plausible location of all the implausible locations is "somewhere after we already called set/setException/setFuture/cancel," in which case we could still call setException(), confident in the knowledge that it will be a no-op.
> 
> Or maybe I'm forgetting something important. Beats me :) But certainly it's hard (impossible?) to write a test that covers this case.
}
          horizon.removeFirst();
          return null;
        }
      };
    }
    final Iterator<N> breadthFirst(Iterator<? extends N> startNodes) {
      return topDown(startNodes, InsertionOrder.BACK);
    }
    final Iterator<N> preOrder(Iterator<? extends N> startNodes) {
      return topDown(startNodes, InsertionOrder.FRONT);
    }
    /**
     * In top-down traversal, an ancestor node is always traversed before any of its descendant
     * nodes. The traversal order among descendant nodes (particularly aunts and nieces) are
     * determined by the {@code InsertionOrder} parameter: nieces are placed at the FRONT before
     * aunts for pre-order; while in BFS they are placed at the BACK after aunts.
     */
    private Iterator<N> topDown(Iterator<? extends N> startNodes, final InsertionOrder order) {
      final Deque<Iterator<? extends N>> horizon = new ArrayDeque<>();
      horizon.add(startNodes);
      return new AbstractIterator<N>() {
        @Override
        protected N computeNext() {
          do {
            N next = visitNext(horizon);
            if (next != null) {
              Iterator<? extends N> successors = successorFunction.successors(next).iterator();
              if (successors.hasNext()) {