#14916 closed bug (fixed)

Missing checks when deriving special classes

Reported by: kosmikus Owned by:
Priority: normal Milestone: 8.4.2
Component: Compiler (Type checker) Version: 8.2.2
Keywords: Deriving Cc: RyanGlScott
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Poor/confusing error message Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s): Phab:D4501
Wiki Page:

Description (last modified by bgamari)

For the following program

{-# LANGUAGE DeriveAnyClass #-}
module T where

import Data.Coerce
import Data.Typeable

data A = MkA deriving ((~) A)
data B = MkB deriving (Coercible B)

the deriving clause for A is accepted without complaints, and the deriving clause for B fails with the following error:

T.hs:8:24: error:
    Top-level bindings for unlifted types aren't allowed:
  |
8 | data B = MkB deriving (Coercible B)
  |                        ^^^^^^^^^^^

Corresponding standalone deriving instances trigger errors saying "Manual instances of this class are not permitted". Probably similar error messages should be triggered here.

Change History (4)

comment:1 Changed 18 months ago by simonpj

Keywords: Deriving added

comment:2 Changed 18 months ago by RyanGlScott

Differential Rev(s): Phab:D4501
Status: newpatch

Luckily, fixing this is quite straightforward by using checkValidInstHead, which is what Phab:D4501 accomplishes.

One thing that's interesting about checkValidInstHead is that is also does validity checks for FlexibleInstances and MultiParamTypeClasses. This means that using checkValidInstHead, unaltered, would result in this program, which is currently accepted by GHC:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module T where

import Control.Monad.Reader

newtype MyReader a = MyReader (Int -> a)
  deriving ( Functor, Applicative, Monad
           , MonadReader Int )

Being rejected due to not enabling FlexibleInstances or MultiParamTypeClasses, since it generates instance MonadReader Int MyReader.

I decided to err on the side of avoiding unnecessary breakage and tweaked checkValidInstHead so as to disable these checks for deriving clauses (just as we do for SPECIALISE instance pragmas today).

comment:3 Changed 18 months ago by Ben Gamari <ben@…>

In 20f14b4/ghc:

Fix #14916 with an additional validity check in deriveTyData

Manually-written instances and standalone-derived instances
have the benefit of having the `checkValidInstHead` function run over
them, which catches manual instances of built-in types like `(~)` and
`Coercible`. However, instances generated from `deriving` clauses
weren't being passed through `checkValidInstHead`, leading to
confusing results as in #14916.

`checkValidInstHead` also has additional validity checks for language
extensions like `FlexibleInstances` and `MultiParamTypeClasses`. Up
until now, GHC has never required these language extensions for
`deriving` clause, so to avoid unnecessary breakage, I opted to
suppress these language extension checks for `deriving` clauses, just
like we currently suppress them for `SPECIALIZE instance` pragmas.

Test Plan: make test TEST=T14916

Reviewers: goldfire, bgamari

Reviewed By: bgamari

Subscribers: rwbarton, thomie, carter

GHC Trac Issues: #14916

Differential Revision: https://phabricator.haskell.org/D4501

comment:4 Changed 18 months ago by bgamari

Description: modified (diff)
Milestone: 8.4.2
Resolution: fixed
Status: patchclosed

Merged to ghc-8.4.

Note: See TracTickets for help on using tickets.