Note [TyVar/TyVar orientation]
See also Note [Fundeps with instances, and equality orientation] where the kind equality orientation is important Given (a ~ b), should we orient the equality as (a~b) or (b~a)? This is a surprisingly tricky question! The question is answered by swapOverTyVars, which is used - in the eager unifier, in GHC.Tc.Utils.Unify.uUnfilledVar1 - in the constraint solver, in GHC.Tc.Solver.Equality.canEqCanLHS2 First note: only swap if you have to! See Note [Avoid unnecessary swaps] So we look for a positive reason to swap, using a three-step test: * Level comparison. If 'a' has deeper level than 'b', put 'a' on the left. See Note [Deeper level on the left] * Priority. If the levels are the same, look at what kind of type variable it is, using 'lhsPriority'. Generally speaking we always try to put a MetaTv on the left in preference to SkolemTv or RuntimeUnkTv, because the MetaTv may be touchable and can be unified. Tie-breaking rules for MetaTvs: - CycleBreakerTv: This is essentially a stand-in for another type; it's untouchable and should have the same priority as a skolem: 0. - TyVarTv: These can unify only with another tyvar, but we can't unify a TyVarTv with a TauTv, because then the TyVarTv could (transitively) get a non-tyvar type. So give these a low priority: 1. - ConcreteTv: These are like TauTv, except they can only unify with a concrete type. So we want to be able to write to them, but not quite as much as TauTvs: 2. - TauTv: This is the common case; we want these on the left so that they can be written to: 3. - RuntimeUnkTv: These aren't really meta-variables used in type inference, but just a convenience in the implementation of the GHCi debugger. Eagerly write to these: 4. See Note [RuntimeUnkTv] in GHC.Runtime.Heap.Inspect. * Names. If the level and priority comparisons are all equal, try to eliminate a TyVar with a System Name in favour of ones with a Name derived from a user type signature * Age. At one point in the past we tried to break any remaining ties by eliminating the younger type variable, based on their Uniques. See Note [Eliminate younger unification variables] (which also explains why we don't do this any more)
References 4
- RuntimeUnkTv GHC.Runtime.Heap.Inspect
- Fundeps with instances, and equality orientation GHC.Tc.Solver.Dict
- Avoid unnecessary swaps GHC.Tc.Utils.Unify
- Deeper level on the left GHC.Tc.Utils.Unify
Referenced by 7
- GHC.Tc.Utils.Unify call site ×4
- Fundeps with instances, and equality orientation GHC.Tc.Solver.Dict
- GHC.Tc.Solver.Equality call site
- Unification preconditions GHC.Tc.Utils.Unify