+ ppr (UfValBinder name ty) = hsep [ppr name, dcolon, pprParendHsType ty]
+ ppr (UfTyBinder name kind) = char '@' <+> pprHsTyVarBndr name kind
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[HsCore-print]{Equality, for interface file checking
+%* *
+%************************************************************************
+
+ ----------------------------------------
+ HACK ALERT
+ ----------------------------------------
+
+Whe comparing UfExprs, we compare names by converting to RdrNames and comparing
+those. Reason: this is used when comparing ufoldings in interface files, and the
+uniques can differ. Converting to RdrNames makes it more like comparing the file
+contents directly. But this is bad: version numbers can change when only alpha-conversion
+has happened.
+
+ The hack shows up in eq_ufVar
+ There are corresponding getOccName calls in MkIface.diffDecls
+
+ ----------------------------------------
+ END OF HACK ALERT
+ ----------------------------------------
+
+
+\begin{code}
+instance (NamedThing name, Ord name) => Eq (UfExpr name) where
+ (==) a b = eq_ufExpr emptyEqHsEnv a b
+
+-----------------
+eq_ufBinder env (UfValBinder n1 t1) (UfValBinder n2 t2) k
+ = eq_hsType env t1 t2 && k (extendEqHsEnv env n1 n2)
+eq_ufBinder env (UfTyBinder n1 k1) (UfTyBinder n2 k2) k
+ = k1==k2 && k (extendEqHsEnv env n1 n2)
+eq_ufBinder _ _ _ _ = False
+
+-----------------
+eq_ufBinders env [] [] k = k env
+eq_ufBinders env (b1:bs1) (b2:bs2) k = eq_ufBinder env b1 b2 (\env -> eq_ufBinders env bs1 bs2 k)
+eq_ufBinders env _ _ _ = False
+
+-----------------
+eq_ufVar :: (NamedThing name, Ord name) => EqHsEnv name -> name -> name -> Bool
+-- Compare *Rdr* names. A real hack to avoid gratuitous
+-- differences when comparing interface files
+eq_ufVar env n1 n2 = case lookupFM env n1 of
+ Just n1 -> toRdrName n1 == toRdrName n2
+ Nothing -> toRdrName n1 == toRdrName n2
+
+
+-----------------
+eq_ufExpr :: (NamedThing name, Ord name) => EqHsEnv name -> UfExpr name -> UfExpr name -> Bool
+eq_ufExpr env (UfVar v1) (UfVar v2) = eq_ufVar env v1 v2
+eq_ufExpr env (UfLit l1) (UfLit l2) = l1 == l2
+eq_ufExpr env (UfLitLit l1 ty1) (UfLitLit l2 ty2) = l1==l2 && eq_hsType env ty1 ty2
+eq_ufExpr env (UfFCall c1 ty1) (UfFCall c2 ty2) = c1==c2 && eq_hsType env ty1 ty2
+eq_ufExpr env (UfType ty1) (UfType ty2) = eq_hsType env ty1 ty2
+eq_ufExpr env (UfTuple n1 as1) (UfTuple n2 as2) = n1==n2 && eqListBy (eq_ufExpr env) as1 as2
+eq_ufExpr env (UfLam b1 body1) (UfLam b2 body2) = eq_ufBinder env b1 b2 (\env -> eq_ufExpr env body1 body2)
+eq_ufExpr env (UfApp f1 a1) (UfApp f2 a2) = eq_ufExpr env f1 f2 && eq_ufExpr env a1 a2
+
+eq_ufExpr env (UfCase s1 b1 as1) (UfCase s2 b2 as2)
+ = eq_ufExpr env s1 s2 &&
+ eqListBy (eq_ufAlt (extendEqHsEnv env b1 b2)) as1 as2
+ where
+ eq_ufAlt env (c1,bs1,r1) (c2,bs2,r2)
+ = eq_ufConAlt env c1 c2 && eq_hsVars env bs1 bs2 (\env -> eq_ufExpr env r1 r2)
+
+eq_ufExpr env (UfLet (UfNonRec b1 r1) x1) (UfLet (UfNonRec b2 r2) x2)
+ = eq_ufExpr env r1 r2 && eq_ufBinder env b1 b2 (\env -> eq_ufExpr env x1 x2)
+
+eq_ufExpr env (UfLet (UfRec as1) x1) (UfLet (UfRec as2) x2)
+ = eq_ufBinders env bs1 bs2 (\env -> eqListBy (eq_ufExpr env) rs1 rs2 && eq_ufExpr env x1 x2)
+ where
+ (bs1,rs1) = unzip as1
+ (bs2,rs2) = unzip as2
+
+eq_ufExpr env (UfNote n1 r1) (UfNote n2 r2)
+ = eq_ufNote n1 n2 && eq_ufExpr env r1 r2
+ where
+ eq_ufNote (UfSCC c1) (UfSCC c2) = c1==c2
+ eq_ufNote (UfCoerce t1) (UfCoerce t2) = eq_hsType env t1 t2
+ eq_ufNote UfInlineCall UfInlineCall = True
+ eq_ufNote UfInlineMe UfInlineMe = True
+ eq_ufNote _ _ = False
+
+eq_ufExpr env _ _ = False
+
+-----------------
+eq_ufConAlt env UfDefault UfDefault = True
+eq_ufConAlt env (UfDataAlt n1) (UfDataAlt n2) = n1==n2
+eq_ufConAlt env (UfTupleAlt c1) (UfTupleAlt c2) = c1==c2
+eq_ufConAlt env (UfLitAlt l1) (UfLitAlt l2) = l1==l2
+eq_ufConAlt env (UfLitLitAlt s1 t1) (UfLitLitAlt s2 t2) = s1==s2 && eq_hsType env t1 t2
+eq_ufConAlt env _ _ = False
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Rules in interface files}
+%* *
+%************************************************************************
+
+\begin{code}
+pprHsIdInfo :: (NamedThing n, Outputable n) => [HsIdInfo n] -> SDoc
+pprHsIdInfo [] = empty
+pprHsIdInfo info = ptext SLIT("{-##") <+> hsep (map ppr_hs_info info) <+> ptext SLIT("##-}")
+
+data HsIdInfo name
+ = HsArity Arity
+ | HsStrictness StrictnessInfo
+ | HsUnfold InlinePragInfo (UfExpr name)
+ | HsNoCafRefs
+ | HsCprInfo
+ | HsWorker name Arity -- Worker, if any see IdInfo.WorkerInfo
+ -- for why we want arity here.
+ deriving( Eq )
+-- NB: Specialisations and rules come in separately and are
+-- only later attached to the Id. Partial reason: some are orphans.
+
+ppr_hs_info (HsUnfold prag unf) = ptext SLIT("__U") <> pprInlinePragInfo prag <+> parens (pprUfExpr noParens unf)
+ppr_hs_info (HsArity arity) = ptext SLIT("__A") <+> int arity
+ppr_hs_info (HsStrictness str) = ptext SLIT("__S") <+> ppStrictnessInfo str
+ppr_hs_info HsNoCafRefs = ptext SLIT("__C")
+ppr_hs_info HsCprInfo = ptext SLIT("__M")
+ppr_hs_info (HsWorker w a) = ptext SLIT("__P") <+> ppr w <+> int a