
#12532: Remove sum and tuple names from knownKeyNames -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: task | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by bgamari): I have an initial attempt (Phab:D2469) at doing this. Here I remove all of the sum and tuples names from `knownKeyNames` implement the codepaths listed above for handling original name lookups and `Name`s from `Unique`s. However, I found that there is one wrinkle: there are actually two places where we need to lookup in the original name cache during interface file deserialization, 1. While deserializing the symbol table. This is the case that I had anticipated and indeed it poses no problem since we have a special encoding for known-key names, so indeed we should never need to do a name cache lookup in this case. 2. To lookup `IfaceTopBndr`s of, e.g., `IfaceDecl`s. This case I only realized after neck-deep in the refactoring and requires a bit more work to handle correctly. = My approach: Changing `IfaceTopBndr` = My approach to (2) is to essentially duplicate the special encoding of known key names that we use for the symbol table for `IfaceTopBndr`. This is done by changing it from a synonym for `OccName` to a sum of, {{{#!hs data IfaceTopBndr = IfaceTopOccName OccName | IfaceKnownKeyName Unique }}} the knock-on changes for this approach go through pretty easily. = An alternative: Using the symbol table = Simon PJ has suggested an alternative: rather than duplicating the known- key encoding, we should instead simply make `IfaceTopBndr` a synonym for `Name`; in principle this would mean that known-key names would "just work" since `IfaceTopBndr` would be encoding via the symbol table. Sadly, it seems that this is too good to be true. The trouble comes from the fingerprinting logic in `MkIface` (namely `addFingerprints`) which works roughly as follows, 1. we look at the `IfaceDecl`s being processed and compute strongly- connect groups of them. 2. we walk the list of groups in dependency order and compute a fingerprint for each. As we progress we maintain an `NameEnv Fingerprint` which maps each name we've looked at to its fingerprint. 3. The fingerprint for a group is determined by serializing it with `Binary` to a buffer and MD5ing the result. However, this isn't quite normal serialization: we override the `putName` operation to, rather than merely serializing the `Name`, lookup the name in the fingerprint environment and instead writing the fingerprint. To see the issue consider what happens when we try to fingerprint a single `IfaceId` with `IfaceTopBndr ~ Name`: the very first thing we do is `put` the `IfaceId`'s `ifName`; this will attempt to lookup the `Name` in the fingerprint environment but this will of course fail since we haven't yet fingerprinted it (which results in a panic exclaiming "urk! lookup local fingerprint"). "Well," you might say, "perhaps we can simply add a special case to the dummy `putName` logic not to attempt to lookup the `Name` of the `IfaceDecl` which we are currently fingerprinting. Sadly, however, this isn't enough since we also need the other names which the decl binds implicitly (e.g. the datacons of a `IfaceData`). It is indeed possible to compute these but all-in-all the situation ends up looking much messier than the relatively simple solution I proposed above. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12532#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler