+ rigid_variable
+ | isOpenSynTyConApp non_var_ty2
+ = -- 'non_var_ty2's outermost constructor is a type family,
+ -- which we may may be able to normalise
+ do { (coi2, ty2') <- tcNormalizeFamInst non_var_ty2
+ ; case coi2 of
+ IdCo -> -- no progress, but maybe after other instantiations
+ defer_unification outer swapped (TyVarTy tv1) ps_ty2
+ ACo co -> -- progress: so lets try again
+ do { traceTc $
+ ppr co <+> text "::"<+> ppr non_var_ty2 <+> text "~" <+>
+ ppr ty2'
+ ; coi <- uUnfilledVar outer swapped tv1 details1 ps_ty2 ty2'
+ ; let coi2' = (if swapped then id else mkSymCoI) coi2
+ ; return $ coi2' `mkTransCoI` coi
+ }
+ }
+ | SkolemTv RuntimeUnkSkol <- details1
+ -- runtime unknown will never match
+ = unifyMisMatch outer swapped (TyVarTy tv1) ps_ty2
+ | otherwise -- defer as a given equality may still resolve this
+ = defer_unification outer swapped (TyVarTy tv1) ps_ty2
+\end{code}
+
+Note [Deferred Unification]
+~~~~~~~~~~~~~~~~~~~~
+We may encounter a unification ty1 = ty2 that cannot be performed syntactically,
+and yet its consistency is undetermined. Previously, there was no way to still
+make it consistent. So a mismatch error was issued.
+
+Now these unfications are deferred until constraint simplification, where type
+family instances and given equations may (or may not) establish the consistency.
+Deferred unifications are of the form
+ F ... ~ ...
+or x ~ ...
+where F is a type function and x is a type variable.
+E.g.
+ id :: x ~ y => x -> y
+ id e = e
+
+involves the unfication x = y. It is deferred until we bring into account the
+context x ~ y to establish that it holds.
+
+If available, we defer original types (rather than those where closed type
+synonyms have already been expanded via tcCoreView). This is as usual, to
+improve error messages.
+
+\begin{code}
+defer_unification :: Bool -- pop innermost context?
+ -> SwapFlag
+ -> TcType
+ -> TcType
+ -> TcM CoercionI
+defer_unification outer True ty1 ty2
+ = defer_unification outer False ty2 ty1
+defer_unification outer False ty1 ty2
+ = do { ty1' <- zonkTcType ty1
+ ; ty2' <- zonkTcType ty2
+ ; traceTc $ text "deferring:" <+> ppr ty1 <+> text "~" <+> ppr ty2
+ ; cotv <- newMetaTyVar TauTv (mkCoKind ty1' ty2')
+ -- put ty1 ~ ty2 in LIE
+ -- Left means "wanted"
+ ; inst <- (if outer then popErrCtxt else id) $
+ mkEqInst (EqPred ty1' ty2') (Left cotv)
+ ; extendLIE inst
+ ; return $ ACo $ TyVarTy cotv }