diff options
author | Vladislav Zavialov <vlad.z.4096@gmail.com> | 2020-02-19 00:07:22 +0300 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2020-02-24 02:05:30 -0500 |
commit | 26e8fff33b1b46ba559538b4519730c60c0d45e5 (patch) | |
tree | 2c9498b02db497fc6083dc80a14b8054e5b0902d /ghc/GHCi | |
parent | 1d9df9e00b021724d570a12d8c6d7870bdc054ca (diff) | |
download | haskell-26e8fff33b1b46ba559538b4519730c60c0d45e5.tar.gz |
Remove Ord SrcLoc, Ord SrcSpan
Before this patch, GHC relied on Ord SrcSpan to identify source elements, by
using SrcSpan as Map keys:
blackList :: Map SrcSpan () -- compiler/GHC/HsToCore/Coverage.hs
instanceMap :: Map SrcSpan Name -- compiler/GHC/HsToCore/Docs.hs
Firstly, this design is not valid in presence of UnhelpfulSpan, as it
distinguishes between UnhelpfulSpan "X" and UnhelpfulSpan "Y", but those
strings are messages for the user, unfit to serve as identifiers for source
elements.
Secondly, this design made it hard to extend SrcSpan with additional data.
Recall that the definition of SrcSpan is:
data SrcSpan =
RealSrcSpan !RealSrcSpan
| UnhelpfulSpan !FastString
Say we want to extend the RealSrcSpan constructor with additional information:
data SrcSpan =
RealSrcSpan !RealSrcSpan !AdditionalInformation
| UnhelpfulSpan !FastString
getAdditionalInformation :: SrcSpan -> AdditionalInformation
getAdditionalInformation (RealSrcSpan _ a) = a
Now, in order for Map SrcSpan to keep working correctly, we must *ignore* additional
information when comparing SrcSpan values:
instance Ord SrcSpan where
compare (RealSrcSpan r1 _) (RealSrcSpan r2 _) = compare r1 r2
...
However, this would violate an important law:
a == b therefore f a == f b
Ignoring AdditionalInformation in comparisons would mean that with
f=getAdditionalInformation, the law above does not hold.
A more robust design is to avoid Ord SrcSpan altogether, which is what this patch implements.
The mappings are changed to use RealSrcSpan instead:
blackList :: Set RealSrcSpan -- compiler/GHC/HsToCore/Coverage.hs
instanceMap :: Map RealSrcSpan Name -- compiler/GHC/HsToCore/Docs.hs
All SrcSpan comparisons are now done with explicit comparison strategies:
SrcLoc.leftmost_smallest
SrcLoc.leftmost_largest
SrcLoc.rightmost_smallest
These strategies are not subject to the law mentioned above and can easily
discard both the string stored in UnhelpfulSpan and AdditionalInformation.
Updates haddock submodule.
Diffstat (limited to 'ghc/GHCi')
-rw-r--r-- | ghc/GHCi/UI.hs | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/ghc/GHCi/UI.hs b/ghc/GHCi/UI.hs index 2559152954..ef78dca036 100644 --- a/ghc/GHCi/UI.hs +++ b/ghc/GHCi/UI.hs @@ -1325,8 +1325,9 @@ printTypeOfNames names = mapM_ (printTypeOfName ) $ sortBy compareNames names compareNames :: Name -> Name -> Ordering -n1 `compareNames` n2 = compareWith n1 `compare` compareWith n2 - where compareWith n = (getOccString n, getSrcSpan n) +n1 `compareNames` n2 = + (compare `on` getOccString) n1 n2 `thenCmp` + (SrcLoc.leftmost_smallest `on` getSrcSpan) n1 n2 printTypeOfName :: GHC.GhcMonad m => Name -> m () printTypeOfName n @@ -2406,7 +2407,7 @@ browseModule bang modl exports_only = do -- has a good source location, then they all should. loc_sort ns | n:_ <- ns, isGoodSrcSpan (nameSrcSpan n) - = sortBy (compare `on` nameSrcSpan) ns + = sortBy (SrcLoc.leftmost_smallest `on` nameSrcSpan) ns | otherwise = occ_sort ns |