deriving-inferred contexts for types with DatatypeContexts are not as general as they should be
Consider this code:
{-# LANGUAGE DatatypeContexts #-}
{-# OPTIONS_GHC -ddump-deriv #-}
module Bug where
data Show a => T a = MkT
deriving Eq
Currently, GHC will generate the following instance for this:
$ /opt/ghc/9.0.1/bin/ghc Bug.hs
[1 of 1] Compiling Bug ( Bug.hs, Bug.o )
==================== Derived instances ====================
Derived class instances:
instance GHC.Show.Show a => GHC.Classes.Eq (Bug.T a) where
(GHC.Classes.==) (Bug.MkT) (Bug.MkT) = GHC.Types.True
This instance is overly constrained, however, as the Show a
constraint is not necessary. Due to the way DatatypeContexts
work, a data constructor only acquires the datatype context if its field types mention any of the type variables used in the datatype context. Because MkT
has no argument types, its type does not acquire a datatype context at all. As proof, the following hand-written instance typechecks:
instance Eq (T a) where
MkT == MkT = True
A derived instance should generate the same code as well. The problem lies here in GHC.Tc.Deriv.Infer
. The code which infers instance contexts for derived instances will simply use the overall datatype context without checking the individual data constructors to see if they actually make use of the datatype context or not. Rather than using the tyConStupidTheta
, I think this code should be made to work over dataConStupidTheta
s instead.
I realize that DatatypeContexts
is a deprecated feature, and fixing this would't seem that important at first blush. I discovered this bug in the context of investigating #20375 (closed)/#20387 (closed), however, and it turns out the current treatment of DatatypeContexts
vis-à-vis deriving
is somewhat of an impediment to fixing those issues.