RebindableSyntax breaks deriving Ord
The code generated with deriving (Ord) includes if-expressions which are subject to rebindable syntax:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RebindableSyntax #-}
import Prelude
class IfThenElse a b where
ifThenElse :: a -> b -> b -> b
instance IfThenElse Bool b where
ifThenElse c x y = if c then x else y
data Foo = Foo | Bar | Baz deriving (Eq, Ord)
main :: IO ()
main = print $ Foo < Bar
when loaded into ghci (7.10, but not specific to that version):
[1 of 1] Compiling Main ( Foo.hs, interpreted )
Foo.hs:13:42:
Bad call to tagToEnum# at type a_aQy
Specify the type by giving a type signature
e.g. (tagToEnum# x) :: Bool
In the expression: (GHC.Prim.tagToEnum# (a# GHC.Prim.<# b#))
In the expression:
if (GHC.Prim.tagToEnum# (a# GHC.Prim.<# b#)) then
LT
else
if (GHC.Prim.tagToEnum# (a# GHC.Prim.==# b#)) then EQ else GT
In a case alternative:
b#
-> if (GHC.Prim.tagToEnum# (a# GHC.Prim.<# b#)) then
LT
else
if (GHC.Prim.tagToEnum# (a# GHC.Prim.==# b#)) then EQ else GT
When typechecking the code for ‘compare’
in a derived instance for ‘Ord Foo’:
To see the code I am typechecking, use -ddump-deriv
Foo.hs:13:42:
No instance for (IfThenElse a0 Ordering)
arising from an if statement
The type variable ‘a0’ is ambiguous
Note: there is a potential instance available:
instance IfThenElse Bool b -- Defined at Foo.hs:10:10
In the expression:
if (GHC.Prim.tagToEnum# (a# GHC.Prim.<# b#)) then
LT
else
if (GHC.Prim.tagToEnum# (a# GHC.Prim.==# b#)) then EQ else GT
In a case alternative:
b#
-> if (GHC.Prim.tagToEnum# (a# GHC.Prim.<# b#)) then
LT
else
if (GHC.Prim.tagToEnum# (a# GHC.Prim.==# b#)) then EQ else GT
In the expression:
case (Main.$con2tag_rjG b) of {
b#
-> if (GHC.Prim.tagToEnum# (a# GHC.Prim.<# b#)) then
LT
else
if (GHC.Prim.tagToEnum# (a# GHC.Prim.==# b#)) then EQ else GT }
When typechecking the code for ‘compare’
in a derived instance for ‘Ord Foo’:
To see the code I am typechecking, use -ddump-deriv
Failed, modules loaded: none.
The if-expressions are generated by nlHsIf, which calls mkHsIf, which uses Just noSyntaxExpr as its first argument. I'm going to add a new function nlBuiltInHsIf which uses Nothing as the first argument, forcing the built-in if (according to Note [Rebindable if]), then use this new function when deriving stuff.
I'll post a patch soonish.
Trac metadata
| Trac field | Value |
|---|---|
| Version | 7.10.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | simonmar |
| Operating system | |
| Architecture |