[GHC] #15552: Infinite loop/panic with an existential type.

GHC ghc-devs at haskell.org
Wed Aug 29 16:37:11 UTC 2018


#15552: Infinite loop/panic with an existential type.
-------------------------------------+-------------------------------------
        Reporter:  howtonotwin       |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:  8.6.1
       Component:  Compiler          |              Version:  8.4.3
      Resolution:                    |             Keywords:  TypeInType,
                                     |  TypeFamilies
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  Compile-time      |  Unknown/Multiple
  crash or panic                     |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:  #14723            |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by goldfire):

 (written concurrently with commen:8)

 After some discussion, Simon and I agreed that (1) from comment:7 would
 nab this bug. But many other questions/observations came up:

 A. This bug is caused by an optimization. What if we don't do the
 optimization? How much is performance affected? We hypothesize: not much.
 This is because while the optimization increases sharing in both time and
 space, this sharing is soon lost (in space, at least) in further passes.

 B. Interestingly, the other zonker (`zonkTcType` and friends in !TcMType)
 does not do this optimization. It could, and it wouldn't be plagued by
 this bug, as `TyCon`s aren't zonked there. So we've done the optimization
 in precisely the places we shouldn't.

 C. The optimization doesn't quite go far enough. Consider `alpha := beta
 -> beta` and `beta := Maybe (Int, Bool)`. Zonking `alpha` replaces the
 contents of the cell with `Maybe (Int, Bool) -> Maybe (Int, Bool)` instead
 of `beta -> beta`. But the next time we zonk `alpha`, we'll still walk
 over the large type `Maybe (Int, Bool) -> Maybe (Int, Bool)`.

 Simon and I puzzled on (C) for quite some time. We came up with a few
 approaches to implementing a better way to avoid redundant zonking. The
 key observation is that once we zonk `alpha` (and update its contents
 according to the current optimization), we don't have to do this again in
 the same zonk.

 a. We can track epoch numbers in the `TcM` monad (in a new mutable cell).
 The epoch would increase at every unification. Every `Indirect` node would
 store the epoch number of the type stored in the node -- that is, the type
 is fully zonked with respect to the stored epoch number. When zonking, if
 we encounter an `Indirect` whose epoch number matches the current epoch
 number, we know that the type is already zonked, and we can avoid
 traversing it.

 b. The idea in (a) doesn't apply only to filled-in metavariables, but to
 all types. The type-checker occasionally zonks types. However, if a type
 has already been zonked and there have been no unifications, then zonking
 it again is a waste of time. If we store an epoch number with every type,
 then we can check this against the global epoch number and skip some
 zonks.

 c. The idea in (b) is a bit heavy, though, requiring alternating proper
 `Type` nodes with epoch numbers in every type. Instead, we could just do
 this in `TcTyVar`s, where we store the epoch number of their kind.

 d. An alternative to epoch numbers is to have each individual zonk track
 which variables' contents are already zonked. This could be done by adding
 an `IORef TyVarEnv` to the local environment to the zonk (replacing the
 `()` environment of a `zonkTcType` or adding to the `ZonkEnv` of a
 `zonkTcTypeToType`). Every time we zonk a variable, add the variable to
 the env't, mapping it to its fully-zonked contents (or, in the case of a
 `TyVar`, a version of the `TyVar` with a zonked kind).

 With any of these ideas, it's not obvious that the work will be worth it,
 as it's hard to know how much redundant zonking we're doing.

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


More information about the ghc-tickets mailing list