- loc = combineCtLoc fl1 fl2
- eqn_pred_locs = improveFromAnother work_item_pred_loc inert_pred_loc
- -- See Note [Efficient Orientation]
-
- ; derived_evs <- mkDerivedFunDepEqns loc eqn_pred_locs
- ; fd_work <- mapM mkCanonicalFEV derived_evs
- -- See Note [Generating extra equalities]
-
- ; mkIRContinue workItem KeepInert (unionManyBags fd_work)
- }
+ work_item_pred_loc = (pty2, pprFlavorArising fl2)
+ fd_eqns = improveFromAnother
+ inert_pred_loc -- the template
+ work_item_pred_loc -- the one we aim to rewrite
+ -- See Note [Efficient Orientation]
+
+ ; m <- rewriteWithFunDeps fd_eqns tys2 fl2
+ ; case m of
+ Nothing -> noInteraction workItem
+ Just (rewritten_tys2, cos2, fd_work)
+
+ | tcEqTypes tys1 rewritten_tys2
+ -> -- Solve him on the spot in this case
+ do { let dict_co = mkTyConCoercion (classTyCon cls1) cos2
+ ; when (isWanted fl2) $ setDictBind d2 (EvCast d1 dict_co)
+ ; mkIRStop "Cls/Cls fundep (solved)" fd_work }
+
+ | isWanted fl2
+ -> -- We could not quite solve him, but we stil rewrite him
+ -- Example: class C a b c | a -> b
+ -- Given: C Int Bool x, Wanted: C Int beta y
+ -- Then rewrite the wanted to C Int Bool y
+ -- but note that is still not identical to the given
+ -- The important thing is that the rewritten constraint is
+ -- inert wrt the given.
+ -- In fact, it is inert wrt all the previous inerts too, so
+ -- we can keep on going rather than sending it back to the work list
+ do { let dict_co = mkTyConCoercion (classTyCon cls1) cos2
+ ; d2' <- newDictVar cls1 rewritten_tys2
+ ; setDictBind d2 (EvCast d2' dict_co)
+ ; let workItem' = workItem { cc_id = d2', cc_tyargs = rewritten_tys2 }
+ ; mkIRContinue "Cls/Cls fundep (partial)" workItem' KeepInert fd_work }
+
+ | otherwise
+ -> ASSERT (isDerived fl2) -- Derived constraints have no evidence,
+ -- so just produce the rewritten constraint
+ let workItem' = workItem { cc_tyargs = rewritten_tys2 }
+ in mkIRContinue "Cls/Cls fundep" workItem' KeepInert fd_work
+ }