Index: lucene/test-framework/src/java/org/apache/lucene/index/AssertingAtomicReader.java
===================================================================
--- lucene/test-framework/src/java/org/apache/lucene/index/AssertingAtomicReader.java	(révision 1467206)
+++ lucene/test-framework/src/java/org/apache/lucene/index/AssertingAtomicReader.java	(copie de travail)
@@ -237,7 +237,7 @@
       super(in);
       try {
         int docid = in.docID();
-        assert docid == -1 || docid == DocIdSetIterator.NO_MORE_DOCS : in.getClass() + ": invalid initial doc id: " + docid;
+        assert docid == -1 : in.getClass() + ": invalid initial doc id: " + docid;
       } catch (UnsupportedOperationException e) {
         if (failOnUnsupportedDocID) {
           throw e;
@@ -256,7 +256,7 @@
       } else {
         state = DocsEnumState.ITERATING;
       }
-      assert docID() == nextDoc;
+      assert super.docID() == nextDoc;
       return doc = nextDoc;
     }
 
@@ -271,13 +271,15 @@
       } else {
         state = DocsEnumState.ITERATING;
       }
-      assert docID() == advanced;
+      assert super.docID() == advanced;
       return doc = advanced;
     }
 
-    // NOTE: We don't assert anything for docId(). Specifically DocsEnum javadocs
-    // are ambiguous with DocIdSetIterator here, DocIdSetIterator says its ok
-    // to call this method before nextDoc(), just that it must be -1 or NO_MORE_DOCS!
+    @Override
+    public int docID() {
+      assert doc == super.docID() : " invalid docID() in " + in.getClass() + " " + super.docID() + " instead of " + doc;
+      return doc;
+    }
 
     @Override
     public int freq() throws IOException {
@@ -298,7 +300,7 @@
     public AssertingDocsAndPositionsEnum(DocsAndPositionsEnum in) {
       super(in);
       int docid = in.docID();
-      assert docid == -1 || docid == DocIdSetIterator.NO_MORE_DOCS : "invalid initial doc id: " + docid;
+      assert docid == -1 : "invalid initial doc id: " + docid;
       doc = -1;
     }
 
@@ -315,7 +317,7 @@
         state = DocsEnumState.ITERATING;
         positionMax = super.freq();
       }
-      assert docID() == nextDoc;
+      assert super.docID() == nextDoc;
       return doc = nextDoc;
     }
 
@@ -333,11 +335,17 @@
         state = DocsEnumState.ITERATING;
         positionMax = super.freq();
       }
-      assert docID() == advanced;
+      assert super.docID() == advanced;
       return doc = advanced;
     }
 
     @Override
+    public int docID() {
+      assert doc == super.docID() : " invalid docID() in " + in.getClass() + " " + super.docID() + " instead of " + doc;
+      return doc;
+    }
+
+    @Override
     public int freq() throws IOException {
       assert state != DocsEnumState.START : "freq() called before nextDoc()/advance()";
       assert state != DocsEnumState.FINISHED : "freq() called after NO_MORE_DOCS";
Index: lucene/core/src/java/org/apache/lucene/search/Scorer.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/Scorer.java	(révision 1467206)
+++ lucene/core/src/java/org/apache/lucene/search/Scorer.java	(copie de travail)
@@ -58,7 +58,7 @@
    * @param collector The collector to which all matching documents are passed.
    */
   public void score(Collector collector) throws IOException {
-    assert docID() == -1 || docID() == NO_MORE_DOCS; // not started
+    assert docID() == -1; // not started
     collector.setScorer(this);
     int doc;
     while ((doc = nextDoc()) != NO_MORE_DOCS) {
Index: lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java	(révision 1467206)
+++ lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java	(copie de travail)
@@ -42,12 +42,8 @@
     this.docScorer = docScorer;
     this.spans = spans;
 
-    if (this.spans.next()) {
-      doc = -1;
-    } else {
-      doc = NO_MORE_DOCS;
-      more = false;
-    }
+    doc = -1;
+    more = spans.next();
   }
 
   @Override
Index: lucene/core/src/java/org/apache/lucene/search/DocIdSetIterator.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/DocIdSetIterator.java	(révision 1467206)
+++ lucene/core/src/java/org/apache/lucene/search/DocIdSetIterator.java	(copie de travail)
@@ -37,7 +37,7 @@
   /**
    * Returns the following:
    * <ul>
-   * <li>-1 or {@link #NO_MORE_DOCS} if {@link #nextDoc()} or
+   * <li><code>-1</code> if {@link #nextDoc()} or
    * {@link #advance(int)} were not called yet.
    * <li>{@link #NO_MORE_DOCS} if the iterator has exhausted.
    * <li>Otherwise it should return the doc ID it is currently on.
@@ -96,8 +96,7 @@
   /** Slow (linear) implementation of {@link #advance} relying on
    *  {@link #nextDoc()} to advance beyond the target position. */
   protected final int slowAdvance(int target) throws IOException {
-    assert docID() == NO_MORE_DOCS // can happen when the enum is not positioned yet
-        || docID() < target;
+    assert docID() < target;
     int doc;
     do {
       doc = nextDoc();
Index: lucene/core/src/java/org/apache/lucene/search/DocIdSet.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/DocIdSet.java	(révision 1467206)
+++ lucene/core/src/java/org/apache/lucene/search/DocIdSet.java	(copie de travail)
@@ -29,20 +29,36 @@
   /** An empty {@code DocIdSet} instance for easy use, e.g. in Filters that hit no documents. */
   public static final DocIdSet EMPTY_DOCIDSET = new DocIdSet() {
     
-    private final DocIdSetIterator iterator = new DocIdSetIterator() {
-      @Override
-      public int advance(int target) { return NO_MORE_DOCS; }
-      @Override
-      public int docID() { return NO_MORE_DOCS; }
-      @Override
-      public int nextDoc() { return NO_MORE_DOCS; }
-      @Override
-      public long cost() { return 0; }
-    };
-    
     @Override
     public DocIdSetIterator iterator() {
-      return iterator;
+      return new DocIdSetIterator() {
+        boolean exhausted = false;
+
+        @Override
+        public int advance(int target) {
+          assert !exhausted;
+          assert target >= 0;
+          exhausted = true;
+          return NO_MORE_DOCS;
+        }
+
+        @Override
+        public int docID() {
+          return exhausted ? NO_MORE_DOCS : -1;
+        }
+
+        @Override
+        public int nextDoc() {
+          assert !exhausted;
+          exhausted = true;
+          return NO_MORE_DOCS;
+        }
+
+        @Override
+        public long cost() {
+          return 0;
+        }
+      };
     }
     
     @Override
@@ -56,7 +72,7 @@
       return null;
     }
   };
-    
+
   /** Provides a {@link DocIdSetIterator} to access the set.
    * This implementation can return <code>null</code> or
    * <code>{@linkplain #EMPTY_DOCIDSET}.iterator()</code> if there
Index: lucene/join/src/java/org/apache/lucene/search/join/TermsIncludingScoreQuery.java
===================================================================
--- lucene/join/src/java/org/apache/lucene/search/join/TermsIncludingScoreQuery.java	(révision 1467206)
+++ lucene/join/src/java/org/apache/lucene/search/join/TermsIncludingScoreQuery.java	(copie de travail)
@@ -193,29 +193,22 @@
     DocsEnum docsEnum;
     DocsEnum reuse;
     int scoreUpto;
+    int doc;
 
     SVInnerScorer(Weight weight, Bits acceptDocs, TermsEnum termsEnum, long cost) {
       super(weight);
       this.acceptDocs = acceptDocs;
       this.termsEnum = termsEnum;
       this.cost = cost;
+      this.doc = -1;
     }
 
     @Override
     public void score(Collector collector) throws IOException {
-      score(collector, NO_MORE_DOCS, nextDocOutOfOrder());
-    }
-
-    @Override
-    public boolean score(Collector collector, int max, int firstDocID)
-        throws IOException {
-      assert collector.acceptsDocsOutOfOrder();
       collector.setScorer(this);
-      int doc;
-      for (doc = firstDocID; doc < max; doc = nextDocOutOfOrder()) {
+      for (int doc = nextDocOutOfOrder(); doc != NO_MORE_DOCS; doc = nextDocOutOfOrder()) {
         collector.collect(doc);
       }
-      return doc != NO_MORE_DOCS;
     }
 
     @Override
@@ -229,7 +222,7 @@
 
     @Override
     public int docID() {
-      return docsEnum != null ? docsEnum.docID() : DocIdSetIterator.NO_MORE_DOCS;
+      return doc;
     }
 
     int nextDocOutOfOrder() throws IOException {
@@ -238,13 +231,13 @@
         if (docId == DocIdSetIterator.NO_MORE_DOCS) {
           docsEnum = null;
         } else {
-          return docId;
+          return doc = docId;
         }
       }
 
       do {
         if (upto == terms.size()) {
-          return DocIdSetIterator.NO_MORE_DOCS;
+          return doc = DocIdSetIterator.NO_MORE_DOCS;
         }
 
         scoreUpto = upto;
@@ -253,7 +246,7 @@
         }
       } while (docsEnum == null);
 
-      return docsEnum.nextDoc();
+      return doc = docsEnum.nextDoc();
     }
 
     @Override
Index: lucene/CHANGES.txt
===================================================================
--- lucene/CHANGES.txt	(révision 1467208)
+++ lucene/CHANGES.txt	(copie de travail)
@@ -19,6 +19,9 @@
   (Nikola Tanković, Uwe Schindler, Chris Male, Mike McCandless,
   Robert Muir)
 
+* LUCENE-4924: Sub-classes of DocIdSetIterator must now return -1 when the
+  iterator is not positioned. (Adrien Grand)
+
 New Features
 
 * LUCENE-4747: Move to Java 7 as minimum Java version.
