Opened 4 years ago

Closed 4 years ago

#11358 closed bug (fixed)

GHC generics has differing conFixity behavior between 7.10.3 and 8.1

Reported by: RyanGlScott Owned by: RyanGlScott
Priority: high Milestone: 8.0.1
Component: Compiler (CodeGen) Version: 8.1
Keywords: Generics Cc: kosmikus
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Incorrect result at runtime Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s): Phab:D1740
Wiki Page:


Compile the following program with GHC 7.10.3 and 8.1:

{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
module Main (main) where

import GHC.Generics

infixr 1 `T`
data T a = T a a deriving Generic
instance HasFixity (T a)

data I a = a `I` a deriving Generic
instance HasFixity (I a)

class HasFixity a where
  fixity :: a -> Fixity
  default fixity :: (Generic a, GHasFixity (Rep a)) => a -> Fixity
  fixity = gfixity . from

class GHasFixity f where
  gfixity :: f a -> Fixity

instance GHasFixity f => GHasFixity (D1 d f) where
  gfixity (M1 x) = gfixity x

instance Constructor c => GHasFixity (C1 c f) where
  gfixity c = conFixity c

main :: IO ()
main = do
  putStrLn $ show (fixity (T "a" "b")) ++ ", " ++ show (fixity ("a" `I` "b"))

On GHC 7.10.3, it yields Prefix, Infix LeftAssociative 9, but on GHC 8.1, it yields Infix RightAssociative 1, Prefix. Why? The implementation of deriving Generic(1) changed slightly in GHC 8.1. Before, it would only assign a fixity of Infix if a constructor was declared infix. But GHC 8.1 no longer checks for this—it first checks if there is a user-supplied fixity declaration, and if so, uses that as the Fixity. Otherwise, it defaults to Prefix, even if the datatype was declared infix!

The design of Fixity perhaps leaves something to be desired, but at the very least, we should ensure nothing Fixity-related breaks for now.

Change History (5)

comment:1 Changed 4 years ago by RyanGlScott

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

comment:2 Changed 4 years ago by bgamari

Milestone: 8.0.1

comment:3 Changed 4 years ago by Ben Gamari <ben@…>

In 852b6030/ghc:

Restore old GHC generics behavior vis-à-vis Fixity

Phab:D493 accidentally changed the way GHC generics looks up `Fixity`
information when deriving `Generic` or `Generic1`. Before, a `Fixity` of
`Infix` would be given only if a data constructor was declared infix,
but now, `Infix` is given to any data constructor that has a fixity
declaration (not to be confused with being declared infix!). This commit
reverts back to the original behavior for consistency's sake.

Fixes #11358.

Test Plan: ./validate

Reviewers: kosmikus, dreixel, austin, bgamari

Reviewed By: bgamari

Subscribers: thomie

Differential Revision:

GHC Trac Issues: #11358

comment:4 Changed 4 years ago by hvr

Status: patchmerge

comment:5 Changed 4 years ago by bgamari

Resolution: fixed
Status: mergeclosed
Note: See TracTickets for help on using tickets.