[GHC] #7788: Recursive type family causes <<loop>>

GHC ghc-devs at haskell.org
Fri Feb 13 15:57:09 UTC 2015


#7788: Recursive type family causes <<loop>>
-------------------------------------+-------------------------------------
        Reporter:  shachaf           |                   Owner:  goldfire
            Type:  bug               |                  Status:  new
        Priority:  normal            |               Milestone:  7.10.1
       Component:  Compiler (Type    |                 Version:  7.6.2
  checker)                           |                Keywords:
      Resolution:                    |            Architecture:
Operating System:  Unknown/Multiple  |  Unknown/Multiple
 Type of failure:  Incorrect result  |               Test Case:
  at runtime                         |                Blocking:
      Blocked By:                    |  Differential Revisions:
 Related Tickets:  #8550, #10079     |
-------------------------------------+-------------------------------------
Changes (by goldfire):

 * related:  #8550 => #8550, #10079


Comment:

 Just had a chat with Simon about all of this. We resolved several things:

 1. The plumbing I have installed (in Phab:D653), using `FlatM` is helpful,
 and it caught errors in `shortCutReduction`.

 2. Having `FlatM` modify a `CtLoc` is wrong, as it means that a certain
 `CtEvidence` suddenly has a new depth. This makes no sense.

 3. Simon was uncertain about the need to bump the stack depth in
 `rewriteEqEvidence`. But, after some thought, this is appropriate (in the
 non-reflexive case): `rewriteEqEvidence` is often called after some
 flattening, and it's quite possible that the flattening reduced some type
 families. We debated various schemes where we would bump only if the
 flattener did indeed reduce a type family (or newtype), and perhaps even
 bump by just the right number of reductions, but these didn't seem to work
 out. A central problem is what to do if we flatten, say, `Either (F a) (G
 b)` to `Either t1 t2`, where `F a` and `G b` took ''different'' numbers of
 steps to reduce. No handling of this scenario seemed adequate. So, we
 always bump (in the non-reflexive case).

 4. `rewriteEqEvidence` checks for deriveds before reflexivity. These
 should be reversed.

 5. The flattener will count reductions ''separately'' from the
 canonicalizer. This amounts to plan (2) in comment:13, where the flattener
 can take `-ftype-function-depth` steps during eager reduction. Then,
 regardless of the number of steps the flattener took, `rewriteEqEvidence`
 will bump only by one. So, the actual number of reductions possible is
 something like the product of the class stack depth and the type function
 depth.

 6. Because of the point above, a programmer has no hope of setting these
 depths correctly when type families or newtypes reduce. Indeed, exactly
 when we hit a certain limit is quite likely to change between minor GHC
 releases. However, these limits are there only to prevent GHC from
 looping. Once a programmer has written their module, confirms that it
 compiles in finite time, it is safe just to disable these checks -- GHC
 will still never produce wrong code; it just might never produce any code
 at all. Thus, the new recommendation when a programmer hits these limits
 is just to disable the check. Disabling the check is infinitely more
 robust than choosing a new, arbitrary limit, likely to change between
 minor releases.

 7. Setting the stack depths to 0 will serve as the marker for infinity.

 8. There are other places where 0 means infinity, such as `st_max_ticks`
 in `SimplMonad.SimplTopEnv` and `TcValidity.TypeSize`. These should be
 abstracted into a new integer+infinity type, to go in `BasicTypes`.

 9. `shortCutReduction` is utterly bogus, and it was a great surprise to
 Simon that the wheels haven't fallen off. We believe that this function
 must not be called at all during building GHC and in the testsuite. I will
 check this, and remove the function if it is unused. It can be fixed
 fairly easily. But as the name implies, it is simply an optimization. If
 it never triggers, then there's no reason to keep around taking up space.
 Simon conjectures that the reason it's not used is due to the new eager
 type family reduction in the flattener.

 10. After all of this is done, it will be possible to move the newtype-
 unwrapping code into the flattener, with a depth check intact.

 The work above is expected to fix this ticket, #8550, and #10079.

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/7788#comment:14>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list