[GHC] #12444: Regression: panic! on inaccessible code with constraint
GHC
ghc-devs at haskell.org
Wed Aug 24 08:32:51 UTC 2016
#12444: Regression: panic! on inaccessible code with constraint
-------------------------------------+-------------------------------------
Reporter: zilinc | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.0.1
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: Compile-time | Unknown/Multiple
crash | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by simonpj):
Here’s a slightly simpler example
{{{
type instance F (Succ x) = Succ (F x)
[W] alpha ~ Succ (F alpha)
}}}
Solving the constraint goes like this:
{{{
Flatten:
[W] alpha ~ Succ fuv (CTyVarEq)
[W] F alpha ~ fuv (CFunEqCan)
Unify alpha := Succ fuv; there’s no occurs check here;
and substitute in the other constraint
[W] F (Succ fuv) ~ fuv (CFunEqCan)
Now we can fire the rule (hooray?)
[W] Succ (F fuv) ~ fuv
}}}
Normally we’d declare at this point that we have figured out what `fuv`
is, so we call `dischargeFmv` to update it in place. But we don’t want
to unify `fuv := Succ (F fuv)` because that’s makes an infinite type.
So instead we turn the fuv into an ordinary unification variable beta,
thus `fuv := beta`. So now we have
{{{
[W] Succ (F beta) ~ beta
}}}
And lo, that’s exactly what we started with, so the whole process
iterates.
This is terrible. It’s a kind of occurs-check loop, but it goes via
function call. If we didn’t do flattening we’d have `[W] alpha ~ Succ
(F alpha)`, which is an occurs check, so we would not substitute for
alpha. Instead we put such occurs-check equalities aside in the
“insoluble”. But we do flatten!
Of course this example isn’t soluble, but this variant is:
{{{
type instance F (Succ a) = Zero
[W] alpha ~ Succ (F alpha)
}}}
Now if we flatten, unify alpha we get
{{{
[W] F (Succ fuv) ~ fuv
}}}
Now fire the rule, and we get
{{{
Zero ~ fuv
}}}
Which is a fine solution. However I would not be too bothered if we
didn’t find it.
So what should we do? Its bad bad bad for the solver to diverge: note
that the type family instance for `F` is perfectly nice.
I wasted an entire evening thinking about and trying several ideas, none
of which worked. One possibility I didn’t try is to beef up the “occurs
check” so that when seeing if `a ~ ty` has an occurs check, we unflatten
on-the-fly to see if `a` occurs.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12444#comment:2>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list