[GHC] #12594: DeriveAnyClass fails to derive some classes
#12594: DeriveAnyClass fails to derive some classes -------------------------------------+------------------------------------- Reporter: ivanm | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: None/Unknown Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- {{{#!hs {-# LANGUAGE DeriveAnyClass, DeriveGeneric #-} import Database.PostgreSQL.Simple import GHC.Generics data Foo = Foo { bar :: Int } deriving (Generic, ToRow) }}} This succeeds using `ghci`, but fails when trying to compile it using `ghc` with the following error message: {{{ • No instance for (Database.PostgreSQL.Simple.ToField.ToField Char) arising from the first field of ‘Foo’ (type ‘Int’) Possible fix: use a standalone 'deriving instance' declaration, so you can specify the instance context yourself • When deriving the instance for (ToRow Foo) }}} However, it works if I use `instance ToRow Foo` instead of relying upon `DeriveAnyClass`. I've tried this with other types instead of `Int`, using `newtype` instead of `data` and having multiple fields in the datatype. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12594> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#12594: DeriveAnyClass fails to derive some classes -------------------------------------+------------------------------------- Reporter: ivanm | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 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: | -------------------------------------+------------------------------------- Changes (by lpsmith): * cc: leon.p.smith@… (added) -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12594#comment:1> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#12594: DeriveAnyClass fails to derive some classes -------------------------------------+------------------------------------- Reporter: ivanm | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 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: | -------------------------------------+------------------------------------- @@ -15,1 +15,1 @@ - • No instance for (Database.PostgreSQL.Simple.ToField.ToField Char) + • No instance for (ToRow Int) New description: {{{#!hs {-# LANGUAGE DeriveAnyClass, DeriveGeneric #-} import Database.PostgreSQL.Simple import GHC.Generics data Foo = Foo { bar :: Int } deriving (Generic, ToRow) }}} This succeeds using `ghci`, but fails when trying to compile it using `ghc` with the following error message: {{{ • No instance for (ToRow Int) arising from the first field of ‘Foo’ (type ‘Int’) Possible fix: use a standalone 'deriving instance' declaration, so you can specify the instance context yourself • When deriving the instance for (ToRow Foo) }}} However, it works if I use `instance ToRow Foo` instead of relying upon `DeriveAnyClass`. I've tried this with other types instead of `Int`, using `newtype` instead of `data` and having multiple fields in the datatype. -- Comment (by hsyl20): With DeriveAnyClass, GHC tries to infer the context for the instance. From compiler/typecheck/TcDeriv.hs: {{{ -- Unfortunately, it is not clear how to determine the context (in case of -- standard deriving; in standalone deriving, the user provides the context). -- GHC uses the same heuristic for figuring out the class context that it uses for -- Eq in the case of *-kinded classes, and for Functor in the case of -- * -> *-kinded classes. That may not be optimal or even wrong. But in such -- cases, standalone deriving can still be used. }}} Here it seems to infer {{{instance ToRow Int => ToRow Foo }}}, hence the error. Maybe we should add the previous comment into the manual. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12594#comment:2> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#12594: DeriveAnyClass fails to derive some classes -------------------------------------+------------------------------------- Reporter: ivanm | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 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 simonpj): Yes, documenting this better would be a Jollly Good Thing. Also pointing out that if the (necessarily fallible) heuristic for deducing a context fails, you can always us a "standalone deriving" declaration to specify the context yourself; it's a bit like adding a type signature. Ryan or someone -- would you like to suggest a documentation patch? Simon -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12594#comment:3> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#12594: DeriveAnyClass fails to derive some classes -------------------------------------+------------------------------------- Reporter: ivanm | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Generics Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * keywords: => Generics Comment: Alternatively, if we fix https://ghc.haskell.org/trac/ghc/ticket/9821#comment:8, then the code above will Just Work. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12594#comment:4> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#12594: DeriveAnyClass fails to derive some classes -------------------------------------+------------------------------------- Reporter: ivanm | Owner: Type: bug | Status: patch Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Generics Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2961 Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * status: new => patch * differential: => Phab:D2961 * milestone: => 8.2.1 Comment: A WIP attempt at fixing this is at Phab:D2961. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12594#comment:5> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#12594: DeriveAnyClass fails to derive some classes -------------------------------------+------------------------------------- Reporter: ivanm | Owner: Type: bug | Status: patch Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Generics Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2961 Wiki Page: | -------------------------------------+------------------------------------- Comment (by Ryan Scott <ryan.gl.scott@…>): In [changeset:"639e702b6129f501c539b158b982ed8489e3d09c/ghc" 639e702/ghc]: {{{ #!CommitTicketReference repository="ghc" revision="639e702b6129f501c539b158b982ed8489e3d09c" Refactor DeriveAnyClass's instance context inference Summary: Currently, `DeriveAnyClass` has two glaring flaws: * It only works on classes whose argument is of kind `*` or `* -> *` (#9821). * The way it infers constraints makes no sense. It basically co-opts the algorithms used to infer contexts for `Eq` (for `*`-kinded arguments) or `Functor` (for `(* -> *)`-kinded arguments). This tends to produce overly constrained instances, which in extreme cases can lead to legitimate things failing to typecheck (#12594). Or even worse, it can trigger GHC panics (#12144 and #12423). This completely reworks the way `DeriveAnyClass` infers constraints to fix these two issues. It now uses the type signatures of the derived class's methods to infer constraints (and to simplify them). A high-level description of how this works is included in the GHC users' guide, and more technical notes on what is going on can be found as comments (and a Note) in `TcDerivInfer`. Fixes #9821, #12144, #12423, #12594. Test Plan: ./validate Reviewers: dfeuer, goldfire, simonpj, austin, bgamari Subscribers: dfeuer, thomie Differential Revision: https://phabricator.haskell.org/D2961 }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12594#comment:6> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#12594: DeriveAnyClass fails to derive some classes -------------------------------------+------------------------------------- Reporter: ivanm | Owner: Type: bug | Status: closed Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 8.0.1 Resolution: fixed | Keywords: Generics Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: | tests/deriving/should_compile/T12594 Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2961 Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * status: patch => closed * testcase: => tests/deriving/should_compile/T12594 * resolution: => fixed -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12594#comment:7> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
participants (1)
-
GHC