Some minor wibbling in printing source locations
[ghc.git] / compiler / basicTypes / SrcLoc.lhs
1 %
2 % (c) The University of Glasgow, 1992-2006
3 %
4
5 \begin{code}
6 {-# OPTIONS_GHC -fno-omit-interface-pragmas #-}
7    -- Workaround for Trac #5252 crashes the bootstrap compiler without -O
8    -- When the earliest compiler we want to boostrap with is
9    -- GHC 7.2, we can make RealSrcLoc properly abstract
10
11
12 -- | This module contains types that relate to the positions of things
13 -- in source files, and allow tagging of those things with locations
14 module SrcLoc (
15         -- * SrcLoc
16         RealSrcLoc,                     -- Abstract
17         SrcLoc(..),
18
19         -- ** Constructing SrcLoc
20         mkSrcLoc, mkRealSrcLoc, mkGeneralSrcLoc,
21
22         noSrcLoc,               -- "I'm sorry, I haven't a clue"
23         generatedSrcLoc,        -- Code generated within the compiler
24         interactiveSrcLoc,      -- Code from an interactive session
25
26         advanceSrcLoc,
27
28         -- ** Unsafely deconstructing SrcLoc
29         -- These are dubious exports, because they crash on some inputs
30         srcLocFile,             -- return the file name part
31         srcLocLine,             -- return the line part
32         srcLocCol,              -- return the column part
33         
34         -- * SrcSpan
35         RealSrcSpan,            -- Abstract
36         SrcSpan(..),
37
38         -- ** Constructing SrcSpan
39         mkGeneralSrcSpan, mkSrcSpan, mkRealSrcSpan,
40         noSrcSpan, 
41         wiredInSrcSpan,         -- Something wired into the compiler
42         srcLocSpan, realSrcLocSpan,
43         combineSrcSpans,
44         
45         -- ** Deconstructing SrcSpan
46         srcSpanStart, srcSpanEnd,
47         realSrcSpanStart, realSrcSpanEnd,
48         srcSpanFileName_maybe,
49
50         -- ** Unsafely deconstructing SrcSpan
51         -- These are dubious exports, because they crash on some inputs
52         srcSpanFile, 
53         srcSpanStartLine, srcSpanEndLine, 
54         srcSpanStartCol, srcSpanEndCol,
55
56         -- ** Predicates on SrcSpan
57         isGoodSrcSpan, isOneLineSpan,
58
59         -- * Located
60         Located, 
61         RealLocated, 
62         GenLocated(..), 
63         
64         -- ** Constructing Located
65         noLoc,
66         mkGeneralLocated,
67         
68         -- ** Deconstructing Located
69         getLoc, unLoc, 
70         
71         -- ** Combining and comparing Located values
72         eqLocated, cmpLocated, combineLocs, addCLoc,
73         leftmost_smallest, leftmost_largest, rightmost, 
74         spans, isSubspanOf
75     ) where
76
77 #include "Typeable.h"
78
79 import Util
80 import Outputable
81 import FastString
82
83 import Data.Bits
84 import Data.Data
85 \end{code}
86
87 %************************************************************************
88 %*                                                                      *
89 \subsection[SrcLoc-SrcLocations]{Source-location information}
90 %*                                                                      *
91 %************************************************************************
92
93 We keep information about the {\em definition} point for each entity;
94 this is the obvious stuff:
95 \begin{code}
96 -- | Represents a single point within a file
97 data RealSrcLoc
98   = SrcLoc      FastString      -- A precise location (file name)
99                 {-# UNPACK #-} !Int             -- line number, begins at 1
100                 {-# UNPACK #-} !Int             -- column number, begins at 1
101
102 data SrcLoc
103   = RealSrcLoc {-# UNPACK #-}!RealSrcLoc
104   | UnhelpfulLoc FastString     -- Just a general indication
105 \end{code}
106
107 %************************************************************************
108 %*                                                                      *
109 \subsection[SrcLoc-access-fns]{Access functions}
110 %*                                                                      *
111 %************************************************************************
112
113 \begin{code}
114 mkSrcLoc :: FastString -> Int -> Int -> SrcLoc
115 mkSrcLoc x line col = RealSrcLoc (mkRealSrcLoc x line col)
116
117 mkRealSrcLoc :: FastString -> Int -> Int -> RealSrcLoc
118 mkRealSrcLoc x line col = SrcLoc x line col
119
120 -- | Built-in "bad" 'SrcLoc' values for particular locations
121 noSrcLoc, generatedSrcLoc, interactiveSrcLoc :: SrcLoc
122 noSrcLoc          = UnhelpfulLoc (fsLit "<no location info>")
123 generatedSrcLoc   = UnhelpfulLoc (fsLit "<compiler-generated code>")
124 interactiveSrcLoc = UnhelpfulLoc (fsLit "<interactive session>")
125
126 -- | Creates a "bad" 'SrcLoc' that has no detailed information about its location
127 mkGeneralSrcLoc :: FastString -> SrcLoc
128 mkGeneralSrcLoc = UnhelpfulLoc 
129
130 -- | Gives the filename of the 'RealSrcLoc'
131 srcLocFile :: RealSrcLoc -> FastString
132 srcLocFile (SrcLoc fname _ _) = fname
133
134 -- | Raises an error when used on a "bad" 'SrcLoc'
135 srcLocLine :: RealSrcLoc -> Int
136 srcLocLine (SrcLoc _ l _) = l
137
138 -- | Raises an error when used on a "bad" 'SrcLoc'
139 srcLocCol :: RealSrcLoc -> Int
140 srcLocCol (SrcLoc _ _ c) = c
141
142 -- | Move the 'SrcLoc' down by one line if the character is a newline,
143 -- to the next 8-char tabstop if it is a tab, and across by one
144 -- character in any other case
145 advanceSrcLoc :: RealSrcLoc -> Char -> RealSrcLoc
146 advanceSrcLoc (SrcLoc f l _) '\n' = SrcLoc f  (l + 1) 1
147 advanceSrcLoc (SrcLoc f l c) '\t' = SrcLoc f  l (((((c - 1) `shiftR` 3) + 1)
148                                                   `shiftL` 3) + 1)
149 advanceSrcLoc (SrcLoc f l c) _    = SrcLoc f  l (c + 1)
150 \end{code}
151
152 %************************************************************************
153 %*                                                                      *
154 \subsection[SrcLoc-instances]{Instance declarations for various names}
155 %*                                                                      *
156 %************************************************************************
157
158 \begin{code}
159 -- SrcLoc is an instance of Ord so that we can sort error messages easily
160 instance Eq SrcLoc where
161   loc1 == loc2 = case loc1 `cmpSrcLoc` loc2 of
162                  EQ     -> True
163                  _other -> False
164
165 instance Eq RealSrcLoc where
166   loc1 == loc2 = case loc1 `cmpRealSrcLoc` loc2 of
167                  EQ     -> True
168                  _other -> False
169
170 instance Ord SrcLoc where
171   compare = cmpSrcLoc
172
173 instance Ord RealSrcLoc where
174   compare = cmpRealSrcLoc
175
176 cmpSrcLoc :: SrcLoc -> SrcLoc -> Ordering
177 cmpSrcLoc (UnhelpfulLoc s1) (UnhelpfulLoc s2) = s1 `compare` s2
178 cmpSrcLoc (UnhelpfulLoc _)  (RealSrcLoc _)    = GT
179 cmpSrcLoc (RealSrcLoc _)    (UnhelpfulLoc _)  = LT
180 cmpSrcLoc (RealSrcLoc l1)   (RealSrcLoc l2)   = (l1 `compare` l2)
181
182 cmpRealSrcLoc :: RealSrcLoc -> RealSrcLoc -> Ordering
183 cmpRealSrcLoc (SrcLoc s1 l1 c1) (SrcLoc s2 l2 c2)
184   = (s1 `compare` s2) `thenCmp` (l1 `compare` l2) `thenCmp` (c1 `compare` c2)
185
186 instance Outputable RealSrcLoc where
187     ppr (SrcLoc src_path src_line src_col)
188       = getPprStyle $ \ sty ->
189         if userStyle sty || debugStyle sty then
190             hcat [ pprFastFilePath src_path, char ':', 
191                    int src_line,
192                    char ':', int src_col
193                  ]
194         else
195             hcat [text "{-# LINE ", int src_line, space,
196                   char '\"', pprFastFilePath src_path, text " #-}"]
197
198 instance Outputable SrcLoc where
199     ppr (RealSrcLoc l) = ppr l
200     ppr (UnhelpfulLoc s)  = ftext s
201
202 instance Data RealSrcSpan where
203   -- don't traverse?
204   toConstr _   = abstractConstr "RealSrcSpan"
205   gunfold _ _  = error "gunfold"
206   dataTypeOf _ = mkNoRepType "RealSrcSpan"
207
208 instance Data SrcSpan where
209   -- don't traverse?
210   toConstr _   = abstractConstr "SrcSpan"
211   gunfold _ _  = error "gunfold"
212   dataTypeOf _ = mkNoRepType "SrcSpan"
213 \end{code}
214
215 %************************************************************************
216 %*                                                                      *
217 \subsection[SrcSpan]{Source Spans}
218 %*                                                                      *
219 %************************************************************************
220
221 \begin{code}
222 {- |
223 A SrcSpan delimits a portion of a text file.  It could be represented
224 by a pair of (line,column) coordinates, but in fact we optimise
225 slightly by using more compact representations for single-line and
226 zero-length spans, both of which are quite common.
227
228 The end position is defined to be the column /after/ the end of the
229 span.  That is, a span of (1,1)-(1,2) is one character long, and a
230 span of (1,1)-(1,1) is zero characters long.
231 -}
232 data RealSrcSpan
233   = SrcSpanOneLine              -- a common case: a single line
234         { srcSpanFile     :: !FastString,
235           srcSpanLine     :: {-# UNPACK #-} !Int,
236           srcSpanSCol     :: {-# UNPACK #-} !Int,
237           srcSpanECol     :: {-# UNPACK #-} !Int
238         }
239
240   | SrcSpanMultiLine
241         { srcSpanFile     :: !FastString,
242           srcSpanSLine    :: {-# UNPACK #-} !Int,
243           srcSpanSCol     :: {-# UNPACK #-} !Int,
244           srcSpanELine    :: {-# UNPACK #-} !Int,
245           srcSpanECol     :: {-# UNPACK #-} !Int
246         }
247
248   | SrcSpanPoint
249         { srcSpanFile     :: !FastString,
250           srcSpanLine     :: {-# UNPACK #-} !Int,
251           srcSpanCol      :: {-# UNPACK #-} !Int
252         }
253 #ifdef DEBUG
254   deriving (Eq, Typeable, Show) -- Show is used by Lexer.x, becuase we
255                                 -- derive Show for Token
256 #else
257   deriving (Eq, Typeable)
258 #endif
259
260 data SrcSpan =
261     RealSrcSpan !RealSrcSpan
262   | UnhelpfulSpan !FastString   -- Just a general indication
263                                 -- also used to indicate an empty span
264
265 #ifdef DEBUG
266   deriving (Eq, Typeable, Show) -- Show is used by Lexer.x, becuase we
267                                 -- derive Show for Token
268 #else
269   deriving (Eq, Typeable)
270 #endif
271
272 -- | Built-in "bad" 'SrcSpan's for common sources of location uncertainty
273 noSrcSpan, wiredInSrcSpan :: SrcSpan
274 noSrcSpan      = UnhelpfulSpan (fsLit "<no location info>")
275 wiredInSrcSpan = UnhelpfulSpan (fsLit "<wired into compiler>")
276
277 -- | Create a "bad" 'SrcSpan' that has not location information
278 mkGeneralSrcSpan :: FastString -> SrcSpan
279 mkGeneralSrcSpan = UnhelpfulSpan
280
281 -- | Create a 'SrcSpan' corresponding to a single point
282 srcLocSpan :: SrcLoc -> SrcSpan
283 srcLocSpan (UnhelpfulLoc str) = UnhelpfulSpan str
284 srcLocSpan (RealSrcLoc l) = RealSrcSpan (realSrcLocSpan l)
285
286 realSrcLocSpan :: RealSrcLoc -> RealSrcSpan
287 realSrcLocSpan (SrcLoc file line col) = SrcSpanPoint file line col
288
289 -- | Create a 'SrcSpan' between two points in a file
290 mkRealSrcSpan :: RealSrcLoc -> RealSrcLoc -> RealSrcSpan
291 mkRealSrcSpan loc1 loc2
292   | line1 == line2 = if col1 == col2
293                         then SrcSpanPoint file line1 col1
294                         else SrcSpanOneLine file line1 col1 col2
295   | otherwise      = SrcSpanMultiLine file line1 col1 line2 col2
296   where
297         line1 = srcLocLine loc1
298         line2 = srcLocLine loc2
299         col1 = srcLocCol loc1
300         col2 = srcLocCol loc2
301         file = srcLocFile loc1
302
303 -- | Create a 'SrcSpan' between two points in a file
304 mkSrcSpan :: SrcLoc -> SrcLoc -> SrcSpan
305 mkSrcSpan (UnhelpfulLoc str) _ = UnhelpfulSpan str
306 mkSrcSpan _ (UnhelpfulLoc str) = UnhelpfulSpan str
307 mkSrcSpan (RealSrcLoc loc1) (RealSrcLoc loc2)
308     = RealSrcSpan (mkRealSrcSpan loc1 loc2)
309
310 -- | Combines two 'SrcSpan' into one that spans at least all the characters
311 -- within both spans. Assumes the "file" part is the same in both inputs
312 combineSrcSpans :: SrcSpan -> SrcSpan -> SrcSpan
313 combineSrcSpans (UnhelpfulSpan _) r = r -- this seems more useful
314 combineSrcSpans l (UnhelpfulSpan _) = l
315 combineSrcSpans (RealSrcSpan span1) (RealSrcSpan span2)
316     = RealSrcSpan (combineRealSrcSpans span1 span2)
317
318 -- | Combines two 'SrcSpan' into one that spans at least all the characters
319 -- within both spans. Assumes the "file" part is the same in both inputs
320 combineRealSrcSpans :: RealSrcSpan -> RealSrcSpan -> RealSrcSpan
321 combineRealSrcSpans span1 span2
322  = if line_start == line_end 
323    then if col_start == col_end
324         then SrcSpanPoint     file line_start col_start
325         else SrcSpanOneLine   file line_start col_start col_end
326    else      SrcSpanMultiLine file line_start col_start line_end col_end
327   where
328     (line_start, col_start) = min (srcSpanStartLine span1, srcSpanStartCol span1)
329                                   (srcSpanStartLine span2, srcSpanStartCol span2)
330     (line_end, col_end)     = max (srcSpanEndLine span1, srcSpanEndCol span1)
331                                   (srcSpanEndLine span2, srcSpanEndCol span2)
332     file = srcSpanFile span1
333 \end{code}
334
335 %************************************************************************
336 %*                                                                      *
337 \subsection[SrcSpan-predicates]{Predicates}
338 %*                                                                      *
339 %************************************************************************
340
341 \begin{code}
342 -- | Test if a 'SrcSpan' is "good", i.e. has precise location information
343 isGoodSrcSpan :: SrcSpan -> Bool
344 isGoodSrcSpan (RealSrcSpan _) = True
345 isGoodSrcSpan (UnhelpfulSpan _) = False
346
347 isOneLineSpan :: SrcSpan -> Bool
348 -- ^ True if the span is known to straddle only one line.
349 -- For "bad" 'SrcSpan', it returns False
350 isOneLineSpan (RealSrcSpan s) = srcSpanStartLine s == srcSpanEndLine s
351 isOneLineSpan (UnhelpfulSpan _) = False
352
353 \end{code}
354
355 %************************************************************************
356 %*                                                                      *
357 \subsection[SrcSpan-unsafe-access-fns]{Unsafe access functions}
358 %*                                                                      *
359 %************************************************************************
360
361 \begin{code}
362
363 srcSpanStartLine :: RealSrcSpan -> Int
364 srcSpanEndLine :: RealSrcSpan -> Int
365 srcSpanStartCol :: RealSrcSpan -> Int
366 srcSpanEndCol :: RealSrcSpan -> Int
367
368 srcSpanStartLine SrcSpanOneLine{ srcSpanLine=l } = l
369 srcSpanStartLine SrcSpanMultiLine{ srcSpanSLine=l } = l
370 srcSpanStartLine SrcSpanPoint{ srcSpanLine=l } = l
371
372 srcSpanEndLine SrcSpanOneLine{ srcSpanLine=l } = l
373 srcSpanEndLine SrcSpanMultiLine{ srcSpanELine=l } = l
374 srcSpanEndLine SrcSpanPoint{ srcSpanLine=l } = l
375
376 srcSpanStartCol SrcSpanOneLine{ srcSpanSCol=l } = l
377 srcSpanStartCol SrcSpanMultiLine{ srcSpanSCol=l } = l
378 srcSpanStartCol SrcSpanPoint{ srcSpanCol=l } = l
379
380 srcSpanEndCol SrcSpanOneLine{ srcSpanECol=c } = c
381 srcSpanEndCol SrcSpanMultiLine{ srcSpanECol=c } = c
382 srcSpanEndCol SrcSpanPoint{ srcSpanCol=c } = c
383
384 \end{code}
385
386 %************************************************************************
387 %*                                                                      *
388 \subsection[SrcSpan-access-fns]{Access functions}
389 %*                                                                      *
390 %************************************************************************
391
392 \begin{code}
393
394 -- | Returns the location at the start of the 'SrcSpan' or a "bad" 'SrcSpan' if that is unavailable
395 srcSpanStart :: SrcSpan -> SrcLoc
396 srcSpanStart (UnhelpfulSpan str) = UnhelpfulLoc str
397 srcSpanStart (RealSrcSpan s) = RealSrcLoc (realSrcSpanStart s)
398
399 -- | Returns the location at the end of the 'SrcSpan' or a "bad" 'SrcSpan' if that is unavailable
400 srcSpanEnd :: SrcSpan -> SrcLoc
401 srcSpanEnd (UnhelpfulSpan str) = UnhelpfulLoc str
402 srcSpanEnd (RealSrcSpan s) = RealSrcLoc (realSrcSpanEnd s)
403
404 realSrcSpanStart :: RealSrcSpan -> RealSrcLoc
405 realSrcSpanStart s = mkRealSrcLoc (srcSpanFile s)
406                                   (srcSpanStartLine s)
407                                   (srcSpanStartCol s)
408
409 realSrcSpanEnd :: RealSrcSpan -> RealSrcLoc
410 realSrcSpanEnd s = mkRealSrcLoc (srcSpanFile s)
411                                 (srcSpanEndLine s)
412                                 (srcSpanEndCol s)
413
414 -- | Obtains the filename for a 'SrcSpan' if it is "good"
415 srcSpanFileName_maybe :: SrcSpan -> Maybe FastString
416 srcSpanFileName_maybe (RealSrcSpan s)   = Just (srcSpanFile s)
417 srcSpanFileName_maybe (UnhelpfulSpan _) = Nothing
418
419 \end{code}
420
421 %************************************************************************
422 %*                                                                      *
423 \subsection[SrcSpan-instances]{Instances}
424 %*                                                                      *
425 %************************************************************************
426
427 \begin{code}
428
429 -- We want to order SrcSpans first by the start point, then by the end point.
430 instance Ord SrcSpan where
431   a `compare` b = 
432      (srcSpanStart a `compare` srcSpanStart b) `thenCmp` 
433      (srcSpanEnd   a `compare` srcSpanEnd   b)
434
435
436 instance Outputable RealSrcSpan where
437     ppr span
438       = getPprStyle $ \ sty ->
439         if userStyle sty || debugStyle sty then
440            pprUserRealSpan True span
441         else
442            hcat [text "{-# LINE ", int (srcSpanStartLine span), space,
443                  char '\"', pprFastFilePath $ srcSpanFile span, text " #-}"]
444
445 instance Outputable SrcSpan where
446     ppr span
447       = getPprStyle $ \ sty ->
448         if userStyle sty || debugStyle sty then
449            pprUserSpan True span
450         else
451            case span of
452            UnhelpfulSpan _ -> panic "Outputable UnhelpfulSpan"
453            RealSrcSpan s -> ppr s
454
455 pprUserSpan :: Bool -> SrcSpan -> SDoc
456 pprUserSpan _         (UnhelpfulSpan s) = ftext s
457 pprUserSpan show_path (RealSrcSpan s)   = pprUserRealSpan show_path s
458
459 pprUserRealSpan :: Bool -> RealSrcSpan -> SDoc
460 pprUserRealSpan show_path (SrcSpanOneLine src_path line start_col end_col)
461   = hcat [ ppWhen show_path (pprFastFilePath src_path <> colon)
462          , int line, char ':', int start_col
463          , ppUnless (end_col - start_col <= 1)
464                     (char '-' <> int (end_col-1)) 
465             -- For single-character or point spans, we just 
466             -- output the starting column number
467          ]
468           
469
470 pprUserRealSpan show_path (SrcSpanMultiLine src_path sline scol eline ecol)
471   = hcat [ ppWhen show_path (pprFastFilePath src_path <> colon)
472          , parens (int sline <> char ',' <>  int scol)
473          , char '-'
474          , parens (int eline <> char ',' <>  
475                    if ecol == 0 then int ecol else int (ecol-1))
476          ]
477
478 pprUserRealSpan show_path (SrcSpanPoint src_path line col)
479   = hcat [ ppWhen show_path $ (pprFastFilePath src_path <> colon)
480          , int line, char ':', int col ]
481 \end{code}
482
483 %************************************************************************
484 %*                                                                      *
485 \subsection[Located]{Attaching SrcSpans to things}
486 %*                                                                      *
487 %************************************************************************
488
489 \begin{code}
490 -- | We attach SrcSpans to lots of things, so let's have a datatype for it.
491 data GenLocated l e = L l e
492   deriving (Eq, Ord, Typeable, Data)
493
494 type Located e = GenLocated SrcSpan e
495 type RealLocated e = GenLocated RealSrcSpan e
496
497 unLoc :: GenLocated l e -> e
498 unLoc (L _ e) = e
499
500 getLoc :: GenLocated l e -> l
501 getLoc (L l _) = l
502
503 noLoc :: e -> Located e
504 noLoc e = L noSrcSpan e
505
506 mkGeneralLocated :: String -> e -> Located e
507 mkGeneralLocated s e = L (mkGeneralSrcSpan (fsLit s)) e
508
509 combineLocs :: Located a -> Located b -> SrcSpan
510 combineLocs a b = combineSrcSpans (getLoc a) (getLoc b)
511
512 -- | Combine locations from two 'Located' things and add them to a third thing
513 addCLoc :: Located a -> Located b -> c -> Located c
514 addCLoc a b c = L (combineSrcSpans (getLoc a) (getLoc b)) c
515
516 -- not clear whether to add a general Eq instance, but this is useful sometimes:
517
518 -- | Tests whether the two located things are equal
519 eqLocated :: Eq a => Located a -> Located a -> Bool
520 eqLocated a b = unLoc a == unLoc b
521
522 -- not clear whether to add a general Ord instance, but this is useful sometimes:
523
524 -- | Tests the ordering of the two located things
525 cmpLocated :: Ord a => Located a -> Located a -> Ordering
526 cmpLocated a b = unLoc a `compare` unLoc b
527
528 instance Functor (GenLocated l) where
529   fmap f (L l e) = L l (f e)
530
531 instance (Outputable l, Outputable e) => Outputable (GenLocated l e) where
532   ppr (L l e) = -- TODO: We can't do this since Located was refactored into
533                 -- GenLocated:
534                 -- Print spans without the file name etc
535                 -- ifPprDebug (braces (pprUserSpan False l))
536                 ifPprDebug (braces (ppr l))
537              $$ ppr e
538 \end{code}
539
540 %************************************************************************
541 %*                                                                      *
542 \subsection{Ordering SrcSpans for InteractiveUI}
543 %*                                                                      *
544 %************************************************************************
545
546 \begin{code}
547 -- | Alternative strategies for ordering 'SrcSpan's
548 leftmost_smallest, leftmost_largest, rightmost :: SrcSpan -> SrcSpan -> Ordering
549 rightmost            = flip compare
550 leftmost_smallest    = compare 
551 leftmost_largest a b = (srcSpanStart a `compare` srcSpanStart b)
552                                 `thenCmp`
553                        (srcSpanEnd b `compare` srcSpanEnd a)
554
555 -- | Determines whether a span encloses a given line and column index
556 spans :: SrcSpan -> (Int, Int) -> Bool
557 spans (UnhelpfulSpan _) _ = panic "spans UnhelpfulSpan"
558 spans (RealSrcSpan span) (l,c) = realSrcSpanStart span <= loc && loc <= realSrcSpanEnd span
559    where loc = mkRealSrcLoc (srcSpanFile span) l c
560
561 -- | Determines whether a span is enclosed by another one
562 isSubspanOf :: SrcSpan -- ^ The span that may be enclosed by the other
563             -> SrcSpan -- ^ The span it may be enclosed by
564             -> Bool
565 isSubspanOf src parent 
566     | srcSpanFileName_maybe parent /= srcSpanFileName_maybe src = False
567     | otherwise = srcSpanStart parent <= srcSpanStart src &&
568                   srcSpanEnd parent   >= srcSpanEnd src
569
570 \end{code}