[GHC] #16322: "deriving newtype instance" generates an infinite loop
GHC
ghc-devs at haskell.org
Fri Feb 15 20:54:40 UTC 2019
#16322: "deriving newtype instance" generates an infinite loop
-------------------------------------+-------------------------------------
Reporter: paf31 | Owner: (none)
Type: bug | Status: infoneeded
Priority: normal | Milestone:
Component: Compiler | Version: 8.6.3
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 RyanGlScott):
Step 2 isn't quite accurate. In general, saying "GHC reduces to looking
for an instance of ..." is a decent intuition for how
`GeneralizedNewtypeDeriving` works, but it breaks down in the particular
case of `C`. Given the standalone `deriving` declaration you've written,
GHC will first generate this code:
{{{#!hs
instance C a b => C (X String a) (X String b) where
c :: Proxy (X String a) -> Int
c = coerce @(Proxy (X String a) -> Int) @(Proxy (X String a) -> Int) c
}}}
At this point, GHC will typecheck this code. GHC has no issues with this
code—the only class constraint that needs to be satisfies in order to
typecheck is `C (X String a) (X String b)`, but since that's exactly the
instance we're defining, this works. Moreover, that's why `c` loops at
runtime, since we're recursively invoking `c` from the same instance
without end. (Note that the `C a b =>` constraint is never really used at
runtime—the only purpose it serves is to satisfy the functional dependency
coverage condition.)
All of this weirdness is ultimately due to the fact that the type of `c`
never mentions `b` anywhere. If `c`'s type were `Proxy b -> Int`, then the
generated code would instead be:
{{{#!hs
instance C a b => C (X String a) (X String b) where
c :: Proxy (X String b) -> Int
c = coerce @(Proxy b -> Int) @(Proxy (X String b) -> Int) c
}}}
In order to typecheck this, GHC would need actually need to satisfy a `C a
b` constraint. In that scenario, it would be fair to summarize the whole
thing as "reducing to looking for an instance of `C a b`". But in the
program you've presented, you have an atypical corner case where the
method's type does not mention the last type parameter of the class, so
the usual intuition doesn't apply.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/16322#comment:9>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list