Skip to content

-Wsimplifiable-class-constraints behaves differently with OVERLAPPING and OVERLAPPABLE

{-# LANGUAGE FlexibleContexts, FlexibleInstances, FunctionalDependencies, MultiParamTypeClasses, UndecidableInstances #-}
module Test where
import Foreign.Ptr

class DescendentOf a b where
    upCast :: Ptr b -> Ptr a
    upCast = castPtr

class ChildOf b c | c -> b

instance {-# OVERLAPPING #-} DescendentOf a a where
    upCast = id

instance (DescendentOf a b, ChildOf b c) => DescendentOf a c

data Value

operateOnValue :: Ptr Value -> IO ()
operateOnValue _ = pure ()

typeOf :: DescendentOf Value v => Ptr v -> IO ()
typeOf = operateOnValue . upCast

The above code results in the following warning with GHC 8.2rc1

Test.hs:21:11: warning: [-Wsimplifiable-class-constraints]
    The constraint ‘DescendentOf Value v’
      matches an instance declaration
    instance (DescendentOf a b, ChildOf b c) => DescendentOf a c
      -- Defined at Test.hs:14:10
    This makes type inference for inner bindings fragile;
      either use MonoLocalBinds, or simplify it using the instance
   |
21 | typeOf :: DescendentOf Value v => Ptr v -> IO ()

However, if I add OVERLAPPABLE to the second instance, the warning disappears because such instances are explicitly excluded in the check for this warning. I think it would make sense to silence this warning also if there is any OVERLAPPING instance that matches. The current warning is confusing since in this case the constraint actually can’t be simplified without changing the meaning of the code (the first instance would no longer match).

Trac metadata
Trac field Value
Version 8.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