Commit 099f9542 authored by Joachim Breitner's avatar Joachim Breitner Committed by thoughtpolice
Browse files

Liberalising IncoherentInstances

(Almost) as suggested by SPJ on

(fixes #8141)
Signed-off-by: thoughtpolice's avatarAustin Seipp <>
parent bab28fb6
......@@ -381,17 +381,17 @@ data OverlapFlag
-- its ambiguous which to choose)
| OverlapOk { isSafeOverlap :: Bool }
-- | Like OverlapOk, but also ignore this instance
-- if it doesn't match the constraint you are
-- trying to resolve, but could match if the type variables
-- in the constraint were instantiated
-- | Silently ignore this instance if you
-- find any other that matches the constraing you
-- are trying to resolve, including when checking if there are instances that
-- do not match, but unify.
-- Example: constraint (Foo [b])
-- instances (Foo [Int]) Incoherent
-- (Foo [a])
-- Without the Incoherent flag, we'd complain that
-- instantiating 'b' would change which instance
-- was chosen
-- was chosen.
| Incoherent { isSafeOverlap :: Bool }
deriving (Eq, Data, Typeable)
......@@ -535,7 +535,7 @@ lookupInstEnv' ie cls tys
= find ((item, map (lookup_tv subst) tpl_tvs) : ms) us rest
-- Does not match, so next check whether the things unify
-- See Note [Overlapping instances] above
-- See Note [Overlapping instances] and Note [Incoherent Instances]
| Incoherent _ <- oflag
= find ms us rest
......@@ -625,12 +625,19 @@ insert_overlapping new_item (item:items)
-- Keep new one
| old_beats_new = item : items
-- Keep old one
| incoherent new_item = item : items -- note [Incoherent Instances]
-- Keep old one
| incoherent item = new_item : items
-- Keep new one
| otherwise = item : insert_overlapping new_item items
-- Keep both
new_beats_old = new_item `beats` item
old_beats_new = item `beats` new_item
incoherent (inst, _) = case is_flag inst of Incoherent _ -> True
_ -> False
(instA, _) `beats` (instB, _)
= overlap_ok &&
isJust (tcMatchTys (mkVarSet (is_tvs instB)) (is_tys instB) (is_tys instA))
......@@ -646,6 +653,37 @@ insert_overlapping new_item (item:items)
_ -> True
Note [Incoherent Instances]
The original motivation for incoherent instances was about the situation where
an instance would unify, but not match. That would be an error, unless the
unifying instances is marked as incoherent. Example:
class C a b c where foo :: (a,b,c)
instance C [a] b Int
instance [incoherent] [Int] b c
instance [incoherent] C a Int c
Thanks to the incoherent flags,
foo :: ([a],b,Int)
works: Only instance one matches, the others just unify, but are marked
So I can write
(foo :: ([a],b,Int)) :: ([Int], Int, Int).
but if that works then I really want to be able to write
foo :: ([Int], Int, Int)
as well. Now all three instances from above match. None is more specific than
another, so none is ruled out by the normal overlapping rules. In order to
allow this, we now (Aug 2013) liberarate the meaning of Incoherent instances to
say: "An incoherent instances can be ignored if there is another matching
instances." This subsumes the ignore-incoheren-unify-logic.
The implementation is in insert_overlapping, where we remove incoherent
instances if there are others.
%* *
......@@ -4542,7 +4542,9 @@ So GHC rejects the program.</para>
If, however, you add the flag <option>-XIncoherentInstances</option>,
GHC will instead pick (C), without complaining about
the problem of subsequent instantiations.
the problem of subsequent instantiations. In general, the flag
<option>-XIncoherentInstances</option> will cause GHC to ignore an instance if
there is another instance that matches the constraint.
Notice that we gave a type signature to <literal>f</literal>, so GHC had to
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment