
#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