+-- | Create a 'SrcSpan' between two points in a file
+mkSrcSpan :: SrcLoc -> SrcLoc -> SrcSpan
+mkSrcSpan (UnhelpfulLoc str) _ = UnhelpfulSpan str
+mkSrcSpan _ (UnhelpfulLoc str) = UnhelpfulSpan str
+mkSrcSpan (RealSrcLoc loc1) (RealSrcLoc loc2)
+ = RealSrcSpan (mkRealSrcSpan loc1 loc2)
+
+-- | Combines two 'SrcSpan' into one that spans at least all the characters
+-- within both spans. Assumes the "file" part is the same in both inputs
+combineSrcSpans :: SrcSpan -> SrcSpan -> SrcSpan
+combineSrcSpans (UnhelpfulSpan _) r = r -- this seems more useful
+combineSrcSpans l (UnhelpfulSpan _) = l
+combineSrcSpans (RealSrcSpan span1) (RealSrcSpan span2)
+ = RealSrcSpan (combineRealSrcSpans span1 span2)
+
+-- | Combines two 'SrcSpan' into one that spans at least all the characters
+-- within both spans. Assumes the "file" part is the same in both inputs
+combineRealSrcSpans :: RealSrcSpan -> RealSrcSpan -> RealSrcSpan
+combineRealSrcSpans span1 span2
+ = if line_start == line_end
+ then if col_start == col_end
+ then SrcSpanPoint file line_start col_start
+ else SrcSpanOneLine file line_start col_start col_end
+ else SrcSpanMultiLine file line_start col_start line_end col_end
+ where
+ (line_start, col_start) = min (srcSpanStartLine span1, srcSpanStartCol span1)
+ (srcSpanStartLine span2, srcSpanStartCol span2)
+ (line_end, col_end) = max (srcSpanEndLine span1, srcSpanEndCol span1)
+ (srcSpanEndLine span2, srcSpanEndCol span2)
+ file = srcSpanFile span1
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[SrcSpan-predicates]{Predicates}
+%* *
+%************************************************************************
+
+\begin{code}
+-- | Test if a 'SrcSpan' is "good", i.e. has precise location information
+isGoodSrcSpan :: SrcSpan -> Bool
+isGoodSrcSpan (RealSrcSpan _) = True
+isGoodSrcSpan (UnhelpfulSpan _) = False