[GHC] #12532: Remove sum and tuple names from knownKeyNames
#12532: Remove sum and tuple names from knownKeyNames -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: task | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: None/Unknown Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- As noted in ticket:12415#comment:5 there are a large number of names inhabiting `knownKeyNames` and therefore the original name cache due to tuples and sums. It shouldn't be so hard to remove these and handle them in an ad-hoc manner: * original name cache lookups (e.g. finding out the `Name` associated with an `OccName`) can been handled by parsing the `OccName`'s string * looking up the `Name` associated with a `Unique` (which is needed in `BinIface` during interface file deserialization) can be done with a set of static functions. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12532> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#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
#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 simonpj): I think the `IfaceTopBndr = Name` idea may be simpler than you think. In `BinIface.putName` we see two cases: {{{ putName ... name | isKnownKeyName name = ...serialise the unique... | otherwise = ...go via the symbol table... }}} where `isKnownKeyName` knows how to parse the uniques for tuples etc. Very well then. In "My approach", when fingerprinting an `IfaceDecl`, you are presumably going to have something like: {{{ putIfaceTopBndr :: IfaceTopBndr -> M () putIfaceTopBndr (IfaeKnownKeyName uniq) = ...uniq... putIFaceTopBndr (IfaceTopNameOccName occ) = ...occ... }}} But instead of making the distiction with a data constructur, you can use `isKnownKeyName` just like `putName`! {{{ putIfaceTopBndr :: IfaceTopBndr -> M () putIFaceTopBndr name | isKnownKeyName name = ...(getUnique name)... | otherwise = ...(getOccName name)... }}} Your proposed `IfaceTopBndr` lets you distinguish the known-key situation. But so does `isKnownKeyName`. (Indeed we could use your `IfaceTopBndr` sum type at ''every'' occurrence of a name, i.e. for `IfaceExtName`.) -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12532#comment:2> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#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): Right, but the problem that I describe is actually quite orthogonal to the known-key encoding issue. The problem is that while generating a fingerprint for an `IfaceDecl` we override the implementation of `putName` in to resolve ensure that the fingerprints the things it refers to are included in its fingerprint. We do this by building up a `NameEnv Fingerprint` as we walk the `IfaceDecl`s in dependency order. Previously this was fine since none of the `Name`s we would serialize were binding occurrences. However, now that `IfaceTopBndr` is also a `Name` we have lost the ability to distinguish binding from non-binding occurrences. This breaks the fingerprinting implementation since we then end up attempting to lookup the `Name` (and implicit `Name`s) of the thing we are trying to fingerprint since its serialization contains a binding `Name`. In writing this the solution here became fairly obvious: simply tell `putName` whether it is serializing a binding or non-binding occurrence. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12532#comment:3> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#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 simonpj):
In writing this the solution here became fairly obvious: simply tell putName whether it is serializing a binding or non-binding occurrence.
Yes, precisely. Hence my name `putIfaceTopBndr`! -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12532#comment:4> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#12532: Remove sum and tuple names from knownKeyNames -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: task | Status: patch 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): Phab:D2467 Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * status: new => patch * differential: => Phab:D2467 -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12532#comment:5> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#12532: Remove sum and tuple names from knownKeyNames -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: task | Status: patch 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): Phab:D2467 Wiki Page: | -------------------------------------+------------------------------------- Comment (by Ben Gamari <ben@…>): In [changeset:"34d933d6a821edf5abfcbee76d9325362fc28a13/ghc" 34d933d/ghc]: {{{ #!CommitTicketReference repository="ghc" revision="34d933d6a821edf5abfcbee76d9325362fc28a13" Clean up handling of known-key Names in interface files Previously BinIface had some dedicated logic for handling tuple names in the symbol table. As it turns out, this logic was essentially dead code as it was superceded by the special handling of known-key things. Here we cull the tuple code-path and use the known-key codepath for all tuple-ish things. This had a surprising number of knock-on effects, * constraint tuple datacons had to be made known-key (previously they were not) * IfaceTopBndr was changed from being a synonym of OccName to a synonym of Name (since we now need to be able to deserialize Names directly from interface files) * the change to IfaceTopBndr complicated fingerprinting, since we need to ensure that we don't go looking for the fingerprint of the thing we are currently fingerprinting in the fingerprint environment (see notes in MkIface). Handling this required distinguishing between binding and non-binding Name occurrences in the Binary serializers. * the original name cache logic which previously lived in IfaceEnv has been moved to a new NameCache module * I ripped tuples and sums out of knownKeyNames since they introduce a very large number of entries. During interface file deserialization we use static functions (defined in the new KnownUniques module) to map from a Unique to a known-key Name (the Unique better correspond to a known-key name!) When we need to do an original name cache lookup we rely on the parser implemented in isBuiltInOcc_maybe. * HscMain.allKnownKeyNames was folded into PrelInfo.knownKeyNames. * Lots of comments were sprinkled about describing the new scheme. Updates haddock submodule. Test Plan: Validate Reviewers: niteria, simonpj, austin, hvr Reviewed By: simonpj Subscribers: simonmar, niteria, thomie Differential Revision: https://phabricator.haskell.org/D2467 GHC Trac Issues: #12532, #12415 }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12532#comment:6> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#12532: Remove sum and tuple names from knownKeyNames -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: task | Status: closed Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 8.0.1 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2467 Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * status: patch => closed * resolution: => fixed * milestone: => 8.2.1 Comment: It has been done. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12532#comment:7> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#12532: Remove sum and tuple names from knownKeyNames -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: task | Status: closed Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 8.0.1 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2467 Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): Also hooray! Long saga here! -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12532#comment:8> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
participants (1)
-
GHC