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 type T 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) and Spec, we call f at type T Int. In the absence of the cross-module specialisation rule, or without -O, GHC would solve the constraint C (T Int), this time using (B). But because of the rule, with -O, it re-uses f_spec. Result: different runtime behaviour.