Skip to content

Overloaded method causes insufficient specialization

The foo function in the following code does not get specialized completely by ghc -O2, even though all the overloaded functions in the module are marked INLINE. Specifically, it gets compiled into a call to a function with an Eq Int dictionary passed at runtime.

module Foo where

class Eq1 f where
  eq1 :: (Eq a) => f a -> f a -> Bool

data F a = F !a !a
data G f a = G !(f a) !(f a)

instance Eq1 F where
  eq1 = \(F a b) (F c d) ->
    -- In order to reproduce the problem, the body of this function needs to be
    -- large enough to prevent GHC from voluntarily inlining it.
    larger $ larger $ larger $ larger $ larger $ larger $
      a == c && b == d
  {-# INLINE eq1 #-}

larger :: a -> a
larger = id
{-# NOINLINE larger #-}

instance (Eq1 f) => Eq1 (G f) where
  eq1 = \(G a b) (G c d) -> eq1 a c && eq1 b d
  {-# INLINE eq1 #-}

foo :: G F Int -> G F Int -> Bool
foo a b = eq1 a b

Looking at the dumps, it looks like there may be a problem is the specializer. It creates a specialization of eq1 with the type

(Eq a) => G F a -> G F a -> Bool

rather than the fully-specialized type:

G F Int -> G F Int -> Bool

Trac metadata
Trac field Value
Version 8.0.1
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information