Note [The superclass story]
We need to add superclass constraints for two reasons:
* For givens [G], they give us a route to proof. E.g.
f :: Ord a => a -> Bool
f x = x == x
We get a Wanted (Eq a), which can only be solved from the superclass
of the Given (Ord a).
* For wanteds [W], they may give useful
functional dependencies. E.g.
class C a b | a -> b where ...
class C a b => D a b where ...
Now a [W] constraint (D Int beta) has (C Int beta) as a superclass
and that might tell us about beta, via C's fundeps. We can get this
by generating a [W] (C Int beta) constraint. We won't use the evidence,
but it may lead to unification.
See Note [Why adding superclasses can help].
For these reasons we want to generate superclass constraints for both
Givens and Wanteds. But:
* (Minor) they are often not needed, so generating them aggressively
is a waste of time.
* (Major) if we want recursive superclasses, there would be an infinite
number of them. Here is a real-life example (#10318);
class (Frac (Frac a) ~ Frac a,
Fractional (Frac a),
IntegralDomain (Frac a))
=> IntegralDomain a where
type Frac a :: *
Notice that IntegralDomain has an associated type Frac, and one
of IntegralDomain's superclasses is another IntegralDomain constraint.
So here's the plan:
1. Eagerly generate superclasses for given (but not wanted)
constraints; see Note [Eagerly expand given superclasses].
This is done using mkStrictSuperClasses in canDictCt, when
we take a non-canonical Given constraint and cannonicalise it.
However stop if you encounter the same class twice. That is,
mkStrictSuperClasses expands eagerly, but has a conservative
termination condition: see Note [Expanding superclasses] in GHC.Tc.Utils.TcType.
2. Solve the wanteds as usual, but do no further expansion of
superclasses for canonical CDictCans in solveSimpleGivens or
solveSimpleWanteds; Note [Danger of adding superclasses during solving]
However, /do/ continue to eagerly expand superclasses for new /given/
/non-canonical/ constraints (canDictCt does this). As #12175
showed, a type-family application can expand to a class constraint,
and we want to see its superclasses for just the same reason as
Note [Eagerly expand given superclasses].
3. If we have any remaining unsolved wanteds
(see Note [When superclasses help] in GHC.Tc.Types.Constraint)
try harder: take both the Givens and Wanteds, and expand
superclasses again. See the calls to expandSuperClasses in
GHC.Tc.Solver.simpl_loop and solveWanteds.
This may succeed in generating (a finite number of) extra Givens,
and extra Wanteds. Both may help the proof.
3a An important wrinkle: only expand Givens from the current level.
Two reasons:
- We only want to expand it once, and that is best done at
the level it is bound, rather than repeatedly at the leaves
of the implication tree
- We may be inside a type where we can't create term-level
evidence anyway, so we can't superclass-expand, say,
(a ~ b) to get (a ~# b). This happened in #15290.
4. Go round to (2) again. This loop (2,3,4) is implemented
in GHC.Tc.Solver.simpl_loop.
The cc_pend_sc field in a CDictCan records whether the superclasses of
this constraint have been expanded. Specifically, in Step 3 we only
expand superclasses for constraints with cc_pend_sc > 0
(i.e. isPendingScDict holds).
See Note [Expanding Recursive Superclasses and ExpansionFuel]
Why do we do this? Two reasons:
* To avoid repeated work, by repeatedly expanding the superclasses of
same constraint,
* To terminate the above loop, at least in the -XNoUndecidableSuperClasses
case. If there are recursive superclasses we could, in principle,
expand forever, always encountering new constraints.
When we take a CNonCanonical or CIrredCan, but end up classifying it
as a CDictCan, we set the cc_pend_sc flag to False. References 6
- Danger of adding superclasses during solving GHC.Tc.Solver.Dict
- Eagerly expand given superclasses GHC.Tc.Solver.Dict
- Why adding superclasses can help GHC.Tc.Solver.Dict
- Expanding Recursive Superclasses and ExpansionFuel GHC.Tc.Solver.Solve
- When superclasses help GHC.Tc.Types.Constraint
- Expanding superclasses GHC.Tc.Utils.TcType
Referenced by 6
- Eagerly expand given superclasses GHC.Tc.Solver.Dict
- GHC.Tc.Solver.Dict call site
- GHC.Tc.Solver.Monad call site
- Expanding Recursive Superclasses and ExpansionFuel GHC.Tc.Solver.Solve
- GHC.Tc.Types.Constraint call site
- When superclasses help GHC.Tc.Types.Constraint