Index: src/java/org/apache/lucene/search/spans/SpanFirstQuery.java
===================================================================
--- src/java/org/apache/lucene/search/spans/SpanFirstQuery.java	(revision 830743)
+++ src/java/org/apache/lucene/search/spans/SpanFirstQuery.java	(working copy)
@@ -163,5 +163,10 @@
     return h;
   }
 
+  @Override
+  public boolean mustBeRewrittenToGetSpans() {
+    return match.mustBeRewrittenToGetSpans();
+  }
 
+
 }
Index: src/java/org/apache/lucene/search/spans/SpanTermQuery.java
===================================================================
--- src/java/org/apache/lucene/search/spans/SpanTermQuery.java	(revision 830743)
+++ src/java/org/apache/lucene/search/spans/SpanTermQuery.java	(working copy)
@@ -83,4 +83,9 @@
     return new TermSpans(reader.termPositions(term), term);
   }
 
+  @Override
+  public boolean mustBeRewrittenToGetSpans() {
+    return false;
+  }
+
 }
Index: src/java/org/apache/lucene/search/spans/FieldMaskingSpanQuery.java
===================================================================
--- src/java/org/apache/lucene/search/spans/FieldMaskingSpanQuery.java	(revision 830743)
+++ src/java/org/apache/lucene/search/spans/FieldMaskingSpanQuery.java	(working copy)
@@ -157,4 +157,14 @@
       ^ getField().hashCode()
       ^ Float.floatToRawIntBits(getBoost());
   }
+
+  @Override
+  public void collectFields(Set<String> fields) {
+    fields.add(maskedQuery.getField());
+  }
+
+  @Override
+  public boolean mustBeRewrittenToGetSpans() {
+    return maskedQuery.mustBeRewrittenToGetSpans();
+  }
 }
Index: src/java/org/apache/lucene/search/spans/SpanQuery.java
===================================================================
--- src/java/org/apache/lucene/search/spans/SpanQuery.java	(revision 830743)
+++ src/java/org/apache/lucene/search/spans/SpanQuery.java	(working copy)
@@ -18,6 +18,7 @@
  */
 
 import java.io.IOException;
+import java.util.Set;
 
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.search.Query;
@@ -37,5 +38,17 @@
   public Weight createWeight(Searcher searcher) throws IOException {
     return new SpanWeight(this, searcher);
   }
-
+  
+  /** Returns the actual fields being used by this query, ignoring the field specified by a {@link FieldMaskingSpanQuery} for example. */
+  public void collectFields(Set<String> fields) {
+    fields.add(getField());
+  }
+  
+  /** Returns true if the {@link #getSpans(IndexReader)} method cannot be called on this SpanQuery before it has been rewritten.
+   *  This method returns <code>true</code> so any new SpanQuery implementation must override this method if it does not require rewriting.
+   */
+  public boolean mustBeRewrittenToGetSpans() {
+    // Assume that it must be rewritten unless the subclass specifies otherwise.
+    return true;
+  }
 }
Index: src/java/org/apache/lucene/search/spans/SpanNotQuery.java
===================================================================
--- src/java/org/apache/lucene/search/spans/SpanNotQuery.java	(revision 830743)
+++ src/java/org/apache/lucene/search/spans/SpanNotQuery.java	(working copy)
@@ -209,4 +209,9 @@
     return h;
   }
 
+  @Override
+  public boolean mustBeRewrittenToGetSpans() {
+    return include.mustBeRewrittenToGetSpans() || exclude.mustBeRewrittenToGetSpans();
+  }
+
 }
Index: src/java/org/apache/lucene/search/spans/SpanOrQuery.java
===================================================================
--- src/java/org/apache/lucene/search/spans/SpanOrQuery.java	(revision 830743)
+++ src/java/org/apache/lucene/search/spans/SpanOrQuery.java	(working copy)
@@ -137,6 +137,15 @@
     return h;
   }
 
+  @Override
+  public boolean mustBeRewrittenToGetSpans() {
+    for (SpanQuery clause : clauses) {
+      if (clause.mustBeRewrittenToGetSpans()) {
+        return true;
+      }
+    }
+    return false;
+  }
 
   private class SpanQueue extends PriorityQueue<Spans> {
     public SpanQueue(int size) {
Index: src/java/org/apache/lucene/search/spans/SpanNearQuery.java
===================================================================
--- src/java/org/apache/lucene/search/spans/SpanNearQuery.java	(revision 830743)
+++ src/java/org/apache/lucene/search/spans/SpanNearQuery.java	(working copy)
@@ -184,4 +184,14 @@
     result ^= (inOrder ? 0x99AFD3BD : 0);
     return result;
   }
+
+  @Override
+  public boolean mustBeRewrittenToGetSpans() {
+    for (SpanQuery clause : clauses) {
+      if (clause.mustBeRewrittenToGetSpans()) {
+        return true;
+      }
+    }
+    return false;
+  }
 }
Index: contrib/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java
===================================================================
--- contrib/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java	(revision 830743)
+++ contrib/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java	(working copy)
@@ -220,16 +220,12 @@
    * @throws IOException
    */
   private void extractWeightedSpanTerms(Map<String,WeightedSpanTerm> terms, SpanQuery spanQuery) throws IOException {
-    Set<Term> nonWeightedTerms = new HashSet<Term>();
-    spanQuery.extractTerms(nonWeightedTerms);
 
     Set<String> fieldNames;
 
     if (fieldName == null) {
       fieldNames = new HashSet<String>();
-      for (final Term queryTerm : nonWeightedTerms) {
-        fieldNames.add(queryTerm.field());
-      }
+      spanQuery.collectFields(fieldNames);
     } else {
       fieldNames = new HashSet<String>(1);
       fieldNames.add(fieldName);
@@ -238,13 +234,30 @@
     if (defaultField != null) {
       fieldNames.add(defaultField);
     }
+    
+    Map<String, SpanQuery> queries = new HashMap<String, SpanQuery>();
+ 
+    Set<Term> nonWeightedTerms = new HashSet<Term>();
+    if (spanQuery.mustBeRewrittenToGetSpans()) {
+      for (final String field : fieldNames) {
+        final SpanQuery rewrittenQuery = (SpanQuery) spanQuery.rewrite(getReaderForField(field));
+        queries.put(field, rewrittenQuery);
+        rewrittenQuery.extractTerms(nonWeightedTerms);
+      }
+    } else {
+      spanQuery.extractTerms(nonWeightedTerms);
+    }
 
     List<PositionSpan> spanPositions = new ArrayList<PositionSpan>();
 
     for (final String field : fieldNames) {
-
       IndexReader reader = getReaderForField(field);
-      Spans spans = spanQuery.getSpans(reader);
+      final Spans spans;
+      if (spanQuery.mustBeRewrittenToGetSpans()) {
+        spans = queries.get(field).getSpans(reader);
+      } else {
+        spans = spanQuery.getSpans(reader);
+      }
 
       // collect span positions
       while (spans.next()) {
