Overlapping instances, incoherence, and optimisation
Segei Meshveliani reports that his docon
library has rather unexpected behaviour with GHC 7.10. See his email.
The effect is that his test module Main
has different runtime behaviour when compiling with and without -O
. This sounds pretty bad.
The reason is this:
-
He has overlapping instances for a class, say
*
instance ... => C (T a)
, call it (A)*
instance C (T Int)
, call it (B)
The actual situation is more complicated of course
-
The instances are defined in different modules.
-
In one module
Spec
* instance (B) is not visible
* there is a function
f :: C a => a -> a
*
f
is called at typeT Int
.
So GHC specialises f
, to f_spec :: T Int -> T Int
, and exports a RULE
RULE "SPEC" f = f_spec :: T Int -> T Int
The idea is that any other module that calls f
at type T Int
can simply re-use the specialised (and presumably much faster) version of f
. But note that since (B) is not visible, so GHC finds a solution using (A), and embodies that in f_spec
.
- In another module,
Use
, which can see (B) andSpec
, we callf
at typeT Int
. In the absence of the cross-module specialisation rule, or without-O
, GHC would solve the constraintC (T Int)
, this time using (B). But because of the rule, with-O
, it re-usesf_spec
. Result: different runtime behaviour.
There is a more detailed discussion on this thread.