Ticket #1799 (closed bug: fixed)

Opened 6 years ago

Last modified 22 months ago

Retain export-list order in ModIface, use it in :browse

Reported by: guest Owned by:
Priority: normal Milestone: 7.2.1
Component: GHCi Version: 6.6.1
Keywords: Cc: claus.reinke@…
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Difficulty: Unknown
Test Case: Blocked By:
Blocking: Related Tickets:

Description

while trying to write a test for an extension of :browse, i encountered an issue with the existing functionality: the order of names is not stable, making it difficult to write meaningful tests for :browse.

a reduced test case & output are appended below, showing that output order is affected by prior usage, in both 6.6.1 and HEAD.

i would prefer for the items to appear in source order, but at the point :browse gets a hand on them, source location information might not be available; sorting by Name would be random due to uniqueIds, and lexicographic sorting would be confusing to users (spreading related items all over the alphabet, instead of keeping the order in which they appear in source and documentation).

is there a way to keep the items in source order, within each module (modules themselves could be sorted lexicographically)? note that alphabetically sorting names would very much be a last resort!

--------------------------------------- testing :browse
$ cat y.hs
import Prelude()
import Data.Maybe(catMaybes,mapMaybe)

$ cat .ghci
:t Data.Maybe.mapMaybe

$ ghcii.sh --version
The Glorious Glasgow Haskell Compilation System, version 6.6.1

$ /cygdrive/c/fptools/ghc/compiler/stage2/ghc-inplace --interactive --version
The Glorious Glasgow Haskell Compilation System, version 6.9.20071019

$ (echo :l y.hs;echo :browse '*Main') | ghcii.sh -v0
Data.Maybe.mapMaybe :: (a -> Maybe b) -> [a] -> [b]
mapMaybe :: (a -> Data.Maybe.Maybe b) -> [a] -> [b]
catMaybes :: [Data.Maybe.Maybe a] -> [a]

$ (echo :l y.hs;echo :browse '*Main') | ghcii.sh -v0 -ignore-dot-ghci
catMaybes :: [Data.Maybe.Maybe a] -> [a]
mapMaybe :: (a -> Data.Maybe.Maybe b) -> [a] -> [b]

$ (echo :l y.hs;echo :browse '*Main') | /cygdrive/c/fptools/ghc/compiler/stage2/ghc-inplace --inter
active  -v0
Data.Maybe.mapMaybe :: (a -> Maybe b) -> [a] -> [b]
mapMaybe :: (a -> Data.Maybe.Maybe b) -> [a] -> [b]
catMaybes :: [Data.Maybe.Maybe a] -> [a]

$ (echo :l y.hs;echo :browse '*Main') | /cygdrive/c/fptools/ghc/compiler/stage2/ghc-inplace --inter
active  -v0 -ignore-dot-ghci
catMaybes :: [Data.Maybe.Maybe a] -> [a]
mapMaybe :: (a -> Data.Maybe.Maybe b) -> [a] -> [b]

Change History

  Changed 6 years ago by guest

i notice that :browse <module> does not seem to suffer from this issue, so the information in GHC.modInfoExports seems more stable than that in GHC.modInfoTopLevelScope. is that an accident or something we could rely on as a basis for ordering names?

would it be possible to take the position of a name in its defining module's minf_exports NameSet?, and add that to the name's srcLoc (in parens, to distinguish from proper srcSpans)? then we could list names in source order where we have the source, and in export order otherwise, both represented by comparing source location info.

btw, i can think of several reasons why a name's srcLoc should be part of the defining module's interface. are the reason's against really stronger?

for:

- :browse could simply list names in source order, which is usually the right thing to do (are there any reasons for making the export order differ from the source order?)

- ghc users could download library sources for libraries installed only as object code, and use ghci to navigate them (Hugs has supported this many many years with :find, and it is terrific both for beginners studying standard library code and for advanced users looking for issues with performance, etc.)

- :ctags/:etags could be made to work with non-interpreted modules, so we could finally put hasktags to rest

- ghc-based ide developers would have more information to work with

- ghc developers could use any of the above to navigate ghc's sources

against:

- interface sizes would increase, though only by a line-number per exported item

- interface comparison would need to ignore line-numbers, both for compatibility and for re-compilation (but doesn't already? the srcLocs are there as dummies)

[claus] (where has the field for the commenter's name disappeared to?)

  Changed 6 years ago by guest

as a workaround, i've got a minor patch that adds a -s option to :browse, so

Prelude> :browse Data.Maybe
data Maybe a = Nothing | Just a
maybe :: b -> (a -> b) -> Maybe a -> b
isJust :: Maybe a -> Bool
isNothing :: Maybe a -> Bool
fromJust :: Maybe a -> a
fromMaybe :: a -> Maybe a -> a
maybeToList :: Maybe a -> [a]
listToMaybe :: [a] -> Maybe a
catMaybes :: [Maybe a] -> [a]
mapMaybe :: (a -> Maybe b) -> [a] -> [b]
Prelude>
Prelude> :browse -s Data.Maybe
data Maybe a = Nothing | Just a
catMaybes :: [Maybe a] -> [a]
fromJust :: Maybe a -> a
fromMaybe :: a -> Maybe a -> a
isJust :: Maybe a -> Bool
isNothing :: Maybe a -> Bool
listToMaybe :: [a] -> Maybe a
mapMaybe :: (a -> Maybe b) -> [a] -> [b]
maybe :: b -> (a -> b) -> Maybe a -> b
maybeToList :: Maybe a -> [a]

i wouldn't want that as the default, but it should enable reproducable tests, and it might occasionally be useful in itself. in the longer term, the default order should be source order, rather than some odd mixture of use/source.

claus

follow-up: ↓ 4   Changed 6 years ago by simonmar

  • priority changed from normal to low
  • summary changed from ghci ':browse *<module>' does not list items in source order to Retain export-list order in ModIface, use it in :browse
  • milestone set to 6.10 branch

In the patch for #1617, I implemented the following:

  • if a module is interpreted, then browse output is in source order
  • otherwise, browse output is alphabetically sorted by name

Ideally I'd like to retain the order of the export list in the ModIface, so that all :browse M output (as opposed to :browse *M) would appear in export-list order. The compiled/interpreted distinction would then disappear. At the moment it appears that md_exports in ModDetails is always sorted by OccName.

in reply to: ↑ 3   Changed 6 years ago by simonpj

Replying to simonmar:

Ideally I'd like to retain the order of the export list in the ModIface, so that all :browse M output (as opposed to :browse *M) would appear in export-list order. The compiled/interpreted distinction would then disappear. At the moment it appears that md_exports in ModDetails is always sorted by OccName.

There seem to be two places where the order might get scrambled:

  • The call to nubAvails in RnNames.rnExports. This combines T(C) with T(D) to give T(C,D). I'm not sure whether you want to retain exactly the former.
  • The groupFM stuff in MkIface.mkIfaceExports, which further groups exports by modules. This part could readily be omitted (although the interface file format would then change).

The other potential cost is that module M( a,b ) would be recorded as a change from module M( b, a ) and hence force recompilation. That probably barely matters, though.

Simon

  Changed 5 years ago by simonmar

  • architecture changed from Unknown to Unknown/Multiple

  Changed 5 years ago by simonmar

  • os changed from Unknown to Unknown/Multiple

  Changed 4 years ago by igloo

  • milestone changed from 6.10 branch to 6.12 branch

  Changed 3 years ago by igloo

  • milestone changed from 6.12 branch to 6.12.3

  Changed 3 years ago by igloo

  • priority changed from low to normal
  • failure set to None/Unknown
  • milestone changed from 6.12.3 to 6.14.1

  Changed 3 years ago by igloo

  • milestone changed from 7.0.1 to 7.0.2

  Changed 2 years ago by igloo

  • milestone changed from 7.0.2 to 7.2.1

  Changed 22 months ago by igloo

  • status changed from new to closed
  • resolution set to fixed

The order is now stable, so closing.

We may in the future use info from the haddock interface to determine the order, instead of what we currently do.

Note: See TracTickets for help on using tickets.