Note [Prioritise Wanteds with empty RewriterSet]
When extending the WorkList, in GHC.Tc.Solver.InertSet.extendWorkListEq,
we prioritise constraints that have no rewriters. Here's why.
Consider this, which came up in T22793:
inert: {}
work list: [W] co_ayf : awq ~ awo
work item: [W] co_ayb : awq ~ awp
==> {just put work item in inert set}
inert: co_ayb : awq ~ awp
work list: {}
work: [W] co_ayf : awq ~ awo
==> {rewrite ayf with co_ayb}
work list: {}
inert: co_ayb : awq ~ awp
co_aym{co_ayb} : awp ~ awo
^ rewritten by ayb
start again in simplify_loop in Solver.hs -----
inert: {}
work list: [W] co_ayb : awq ~ awp
work: co_aym{co_ayb} : awp ~ awo
==> {add to inert set}
inert: co_aym{co_ayb} : awp ~ awo
work list: {}
work: co_ayb : awq ~ awp
==> {rewrite co_ayb}
inert: co_aym{co_ayb} : awp ~ awo
co_ayp{co_aym} : awq ~ awo
work list: {}
Now both wanteds have been rewriten by the other! This happened because
in our simplify_loop iteration, we happened to start with co_aym. All would have
been well if we'd started with the (not-rewritten) co_ayb and gotten it into the
inert set.
With that in mind, we /prioritise/ the work-list to put
constraints with no rewriters first. This prioritisation
is done in `GHC.Tc.Solver.Monad.selectNextWorkItem`.
Wrinkles
(PER1) When picking the next work item, before checking for an empty RewriterSet
in GHC.Tc.Solver.Monad.selectNextWorkItem, we zonk the RewriterSet, because
some of those CoercionHoles may have been filled in since we last looked.
(PER2) Despite the prioritisation, it is hard to be /certain/ that we can't end up
in a situation where all of the Wanteds have rewritten each other. In
order to report /some/ error in this case, we simply report all the
Wanteds. The user will get a perhaps-confusing error message, but they've
written a confusing program! (T22707 and T22793 were close, but they do
not exhibit this behaviour.) So belt and braces: see the `suppress`
stuff in GHC.Tc.Errors.mkErrorItem. References 0
This Note does not link to any other.
Referenced by 7
- GHC.Tc.Solver.InertSet call site ×3
- Wanteds rewrite Wanteds GHC.Tc.Types.Constraint ×2
- Unify only if the rewriter set is empty GHC.Tc.Solver.Equality
- GHC.Tc.Solver.Monad call site