
#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): Ah, I misinterpreted your comment—I thought that you were implying that the code was infinitely looping at compile-time, not runtime. My apologies. The code that `deriving newtype instance C a b => C (X String a) (X String b)` generates is expected behavior, as it turns out. From the [https://downloads.haskell.org/~ghc/8.6.3/docs/html/users_guide/glasgow_exts.... #extension-StandaloneDeriving users' guide section] on `StandaloneDeriving`:
The stand-alone syntax is generalised for newtypes in exactly the same way that ordinary deriving clauses are generalised [...]. For example:
{{{#!hs newtype Foo a = MkFoo (State Int a)
deriving instance MonadState Int Foo }}}
GHC always treats the //last// parameter of the instance (Foo in this example) as the type whose instance is being derived.
In other words, the generated code will `coerce` underneath the last type argument, and nothing more. In your example, you have: {{{#!hs class C a b | a -> b, b -> a where c :: Proxy a -> Int newtype X a b = X b deriving newtype instance C a b => C (X String a) (X String b) }}} This will `coerce` from `X String b` to `b`, and nothing more. Because the type of `c` happens to never mention the last type parameter of `C`, this results in the "identity coercion" behavior you see with `-ddump-deriv`. It's a bit strange, but there's a certain consistency to it. After all, `deriving newtype instance C a b => C (X String a) (X String b)` could mean three different things: 1. Coerce underneath `X String a` only. 2. Coerce underneath `X String b` only. 3. Coerce underneath `X String a` and `X String b`. In general, if a multi-parameter type class has //n// type parameters, then there are 2^//n//^ - 1 different potential choices of code to generate. Since `deriving` clauses only `coerce` underneath the last type parameter, `StandaloneDeriving` picks the same convention. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16322#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler