2 % (c) The GRASP/AQUA Project, Glasgow University, 1993-1998
4 %************************************************************************
6 \section[HsCore]{Core-syntax unfoldings in Haskell interface files}
8 %************************************************************************
10 We could either use this, or parameterise @GenCoreExpr@ on @Types@ and
11 @TyVars@ as well. Currently trying the former... MEGA SIGH.
15 module IfaceType, -- Re-export all this
17 IfaceDecl(..), IfaceClassOp(..), IfaceConDecl(..), IfaceConDecls(..),
18 IfaceExpr(..), IfaceAlt, IfaceNote(..),
19 IfaceBinding(..), IfaceConAlt(..), IfaceIdInfo(..),
20 IfaceInfoItem(..), IfaceRule(..), IfaceInst(..),
25 -- Converting things to IfaceSyn
26 tyThingToIfaceDecl, instanceToIfaceInst, coreRuleToIfaceRule,
29 IfaceEq(..), (&&&), bool, eqListBy, eqMaybeBy,
30 eqIfDecl, eqIfInst, eqIfRule,
33 pprIfaceExpr, pprIfaceDecl, pprIfaceDeclHead
36 #include "HsVersions.h"
41 import FunDeps ( pprFundeps )
42 import NewDemand ( StrictSig, pprIfaceStrictSig )
43 import TcType ( deNoteType )
44 import Type ( TyThing(..), splitForAllTys, funResultTy )
45 import InstEnv ( Instance(..), OverlapFlag )
46 import Id ( Id, idName, idType, idInfo, idArity, isDataConWorkId_maybe, isFCallId_maybe )
47 import NewDemand ( isTopSig )
48 import IdInfo ( IdInfo, CafInfo(..), WorkerInfo(..),
49 arityInfo, cafInfo, newStrictnessInfo,
50 workerInfo, unfoldingInfo, inlinePragInfo )
51 import TyCon ( TyCon, ArgVrcs, AlgTyConRhs(..), isRecursiveTyCon, isForeignTyCon,
52 isSynTyCon, isAlgTyCon, isPrimTyCon, isFunTyCon,
53 isTupleTyCon, tupleTyConBoxity, tyConStupidTheta,
54 tyConHasGenerics, tyConArgVrcs, synTyConRhs,
55 tyConArity, tyConTyVars, algTyConRhs, tyConExtName )
56 import DataCon ( dataConName, dataConSig, dataConFieldLabels, dataConStrictMarks,
57 dataConTyCon, dataConIsInfix, isVanillaDataCon )
58 import Class ( FunDep, DefMeth, classExtraBigSig, classTyCon )
59 import OccName ( OccName, OccEnv, emptyOccEnv,
60 lookupOccEnv, extendOccEnv, parenSymOcc,
61 OccSet, unionOccSets, unitOccSet )
62 import Name ( Name, NamedThing(..), nameOccName, isExternalName )
63 import CostCentre ( CostCentre, pprCostCentreCore )
64 import Literal ( Literal )
65 import ForeignCall ( ForeignCall )
66 import TysPrim ( alphaTyVars )
67 import BasicTypes ( Arity, Activation(..), StrictnessMark,
68 RecFlag(..), boolToRecFlag, Boxity(..),
69 isAlwaysActive, tupleParens )
72 import Maybes ( catMaybes )
73 import Util ( lengthIs )
76 infix 4 `eqIfExt`, `eqIfIdInfo`, `eqIfType`
80 %************************************************************************
82 Data type declarations
84 %************************************************************************
88 = IfaceId { ifName :: OccName,
90 ifIdInfo :: IfaceIdInfo }
92 | IfaceData { ifName :: OccName, -- Type constructor
93 ifTyVars :: [IfaceTvBndr], -- Type variables
94 ifCtxt :: IfaceContext, -- The "stupid theta"
95 ifCons :: IfaceConDecls, -- Includes new/data info
96 ifRec :: RecFlag, -- Recursive or not?
98 ifGeneric :: Bool -- True <=> generic converter functions available
99 } -- We need this for imported data decls, since the
100 -- imported modules may have been compiled with
101 -- different flags to the current compilation unit
103 | IfaceSyn { ifName :: OccName, -- Type constructor
104 ifTyVars :: [IfaceTvBndr], -- Type variables
106 ifSynRhs :: IfaceType -- synonym expansion
109 | IfaceClass { ifCtxt :: IfaceContext, -- Context...
110 ifName :: OccName, -- Name of the class
111 ifTyVars :: [IfaceTvBndr], -- Type variables
112 ifFDs :: [FunDep OccName], -- Functional dependencies
113 ifSigs :: [IfaceClassOp], -- Method signatures
114 ifRec :: RecFlag, -- Is newtype/datatype associated with the class recursive?
115 ifVrcs :: ArgVrcs -- ... and what are its argument variances ...
118 | IfaceForeign { ifName :: OccName, -- Needs expanding when we move beyond .NET
119 ifExtName :: Maybe FastString }
121 data IfaceClassOp = IfaceClassOp OccName DefMeth IfaceType
122 -- Nothing => no default method
123 -- Just False => ordinary polymorphic default method
124 -- Just True => generic default method
127 = IfAbstractTyCon -- No info
128 | IfDataTyCon [IfaceConDecl] -- data type decls
129 | IfNewTyCon IfaceConDecl -- newtype decls
131 visibleIfConDecls :: IfaceConDecls -> [IfaceConDecl]
132 visibleIfConDecls IfAbstractTyCon = []
133 visibleIfConDecls (IfDataTyCon cs) = cs
134 visibleIfConDecls (IfNewTyCon c) = [c]
138 ifConOcc :: OccName, -- Constructor name
139 ifConInfix :: Bool, -- True <=> declared infix
140 ifConArgTys :: [IfaceType], -- Arg types
141 ifConStricts :: [StrictnessMark], -- Empty (meaning all lazy), or 1-1 corresp with arg types
142 ifConFields :: [OccName] } -- ...ditto... (field labels)
144 ifConOcc :: OccName, -- Constructor name
145 ifConTyVars :: [IfaceTvBndr], -- All tyvars
146 ifConCtxt :: IfaceContext, -- Non-stupid context
147 ifConArgTys :: [IfaceType], -- Arg types
148 ifConResTys :: [IfaceType], -- Result type args
149 ifConStricts :: [StrictnessMark] } -- Empty (meaning all lazy), or 1-1 corresp with arg types
152 = IfaceInst { ifInstCls :: IfaceExtName, -- See comments with
153 ifInstTys :: [Maybe IfaceTyCon], -- the defn of Instance
154 ifDFun :: OccName, -- The dfun
155 ifOFlag :: OverlapFlag, -- Overlap flag
156 ifInstOrph :: Maybe OccName } -- See is_orph in defn of Instance
157 -- There's always a separate IfaceDecl for the DFun, which gives
158 -- its IdInfo with its full type and version number.
159 -- The instance declarations taken together have a version number,
160 -- and we don't want that to wobble gratuitously
161 -- If this instance decl is *used*, we'll record a usage on the dfun;
162 -- and if the head does not change it won't be used if it wasn't before
166 ifRuleName :: RuleName,
167 ifActivation :: Activation,
168 ifRuleBndrs :: [IfaceBndr], -- Tyvars and term vars
169 ifRuleHead :: IfaceExtName, -- Head of lhs
170 ifRuleArgs :: [IfaceExpr], -- Args of LHS
171 ifRuleRhs :: IfaceExpr,
172 ifRuleOrph :: Maybe OccName -- Just like IfaceInst
176 = NoInfo -- When writing interface file without -O
177 | HasInfo [IfaceInfoItem] -- Has info, and here it is
179 -- Here's a tricky case:
180 -- * Compile with -O module A, and B which imports A.f
181 -- * Change function f in A, and recompile without -O
182 -- * When we read in old A.hi we read in its IdInfo (as a thunk)
183 -- (In earlier GHCs we used to drop IdInfo immediately on reading,
184 -- but we do not do that now. Instead it's discarded when the
185 -- ModIface is read into the various decl pools.)
186 -- * The version comparsion sees that new (=NoInfo) differs from old (=HasInfo *)
187 -- and so gives a new version.
191 | HsStrictness StrictSig
192 | HsInline Activation
195 | HsWorker IfaceExtName Arity -- Worker, if any see IdInfo.WorkerInfo
196 -- for why we want arity here.
197 -- NB: we need IfaceExtName (not just OccName) because the worker
198 -- can simplify to a function in another module.
199 -- NB: Specialisations and rules come in separately and are
200 -- only later attached to the Id. Partial reason: some are orphans.
202 --------------------------------
205 | IfaceExt IfaceExtName
206 | IfaceType IfaceType
207 | IfaceTuple Boxity [IfaceExpr] -- Saturated; type arguments omitted
208 | IfaceLam IfaceBndr IfaceExpr
209 | IfaceApp IfaceExpr IfaceExpr
210 | IfaceCase IfaceExpr OccName IfaceType [IfaceAlt]
211 | IfaceLet IfaceBinding IfaceExpr
212 | IfaceNote IfaceNote IfaceExpr
214 | IfaceFCall ForeignCall IfaceType
216 data IfaceNote = IfaceSCC CostCentre
217 | IfaceCoerce IfaceType
220 | IfaceCoreNote String
222 type IfaceAlt = (IfaceConAlt, [OccName], IfaceExpr)
223 -- Note: OccName, not IfaceBndr (and same with the case binder)
224 -- We reconstruct the kind/type of the thing from the context
225 -- thus saving bulk in interface files
227 data IfaceConAlt = IfaceDefault
228 | IfaceDataAlt OccName
229 | IfaceTupleAlt Boxity
230 | IfaceLitAlt Literal
233 = IfaceNonRec IfaceIdBndr IfaceExpr
234 | IfaceRec [(IfaceIdBndr, IfaceExpr)]
238 %************************************************************************
240 \subsection[HsCore-print]{Printing Core unfoldings}
242 %************************************************************************
244 ----------------------------- Printing IfaceDecl ------------------------------------
247 instance Outputable IfaceDecl where
250 pprIfaceDecl (IfaceId {ifName = var, ifType = ty, ifIdInfo = info})
251 = sep [ ppr var <+> dcolon <+> ppr ty,
254 pprIfaceDecl (IfaceForeign {ifName = tycon})
255 = hsep [ptext SLIT("foreign import type dotnet"), ppr tycon]
257 pprIfaceDecl (IfaceSyn {ifName = tycon, ifTyVars = tyvars, ifSynRhs = mono_ty, ifVrcs = vrcs})
258 = hang (ptext SLIT("type") <+> pprIfaceDeclHead [] tycon tyvars)
259 4 (vcat [equals <+> ppr mono_ty,
262 pprIfaceDecl (IfaceData {ifName = tycon, ifGeneric = gen, ifCtxt = context,
263 ifTyVars = tyvars, ifCons = condecls,
264 ifRec = isrec, ifVrcs = vrcs})
265 = hang (pp_nd <+> pprIfaceDeclHead context tycon tyvars)
266 4 (vcat [pprVrcs vrcs, pprRec isrec, pprGen gen, pp_condecls tycon condecls])
268 pp_nd = case condecls of
269 IfAbstractTyCon -> ptext SLIT("data")
270 IfDataTyCon _ -> ptext SLIT("data")
271 IfNewTyCon _ -> ptext SLIT("newtype")
273 pprIfaceDecl (IfaceClass {ifCtxt = context, ifName = clas, ifTyVars = tyvars,
274 ifFDs = fds, ifSigs = sigs, ifVrcs = vrcs, ifRec = isrec})
275 = hang (ptext SLIT("class") <+> pprIfaceDeclHead context clas tyvars <+> pprFundeps fds)
276 4 (vcat [pprVrcs vrcs,
280 pprVrcs vrcs = ptext SLIT("Variances") <+> ppr vrcs
281 pprRec isrec = ptext SLIT("RecFlag") <+> ppr isrec
282 pprGen True = ptext SLIT("Generics: yes")
283 pprGen False = ptext SLIT("Generics: no")
285 instance Outputable IfaceClassOp where
286 ppr (IfaceClassOp n dm ty) = ppr n <+> ppr dm <+> dcolon <+> ppr ty
288 pprIfaceDeclHead :: IfaceContext -> OccName -> [IfaceTvBndr] -> SDoc
289 pprIfaceDeclHead context thing tyvars
290 = hsep [pprIfaceContext context, parenSymOcc thing (ppr thing), pprIfaceTvBndrs tyvars]
292 pp_condecls tc IfAbstractTyCon = ptext SLIT("{- abstract -}")
293 pp_condecls tc (IfNewTyCon c) = equals <+> pprIfaceConDecl tc c
294 pp_condecls tc (IfDataTyCon cs) = equals <+> sep (punctuate (ptext SLIT(" |"))
295 (map (pprIfaceConDecl tc) cs))
297 pprIfaceConDecl tc (IfVanillaCon {
298 ifConOcc = name, ifConInfix = is_infix,
299 ifConArgTys = arg_tys,
300 ifConStricts = strs, ifConFields = fields })
301 = sep [ppr name <+> sep (map pprParendIfaceType arg_tys),
302 if is_infix then ptext SLIT("Infix") else empty,
303 if null strs then empty
304 else nest 4 (ptext SLIT("Stricts:") <+> hsep (map ppr strs)),
305 if null fields then empty
306 else nest 4 (ptext SLIT("Fields:") <+> hsep (map ppr fields))]
308 pprIfaceConDecl tc (IfGadtCon {
310 ifConTyVars = tvs, ifConCtxt = ctxt,
311 ifConArgTys = arg_tys, ifConResTys = res_tys,
312 ifConStricts = strs })
313 = sep [ppr name <+> dcolon <+> pprIfaceForAllPart tvs ctxt (ppr con_tau),
314 if null strs then empty
315 else nest 4 (ptext SLIT("Stricts:") <+> hsep (map ppr strs))]
317 con_tau = foldr1 IfaceFunTy (arg_tys ++ [tc_app])
318 tc_app = IfaceTyConApp (IfaceTc (LocalTop tc)) res_tys
319 -- Gruesome, but jsut for debug print
321 instance Outputable IfaceRule where
322 ppr (IfaceRule { ifRuleName = name, ifActivation = act, ifRuleBndrs = bndrs,
323 ifRuleHead = fn, ifRuleArgs = args, ifRuleRhs = rhs })
324 = sep [hsep [doubleQuotes (ftext name), ppr act,
325 ptext SLIT("forall") <+> pprIfaceBndrs bndrs],
326 nest 2 (sep [ppr fn <+> sep (map (pprIfaceExpr parens) args),
327 ptext SLIT("=") <+> ppr rhs])
330 instance Outputable IfaceInst where
331 ppr (IfaceInst {ifDFun = dfun_id, ifOFlag = flag,
332 ifInstCls = cls, ifInstTys = mb_tcs})
333 = hang (ptext SLIT("instance") <+> ppr flag
334 <+> ppr cls <+> brackets (pprWithCommas ppr_mb mb_tcs))
335 2 (equals <+> ppr dfun_id)
338 ppr_mb (Just tc) = ppr tc
342 ----------------------------- Printing IfaceExpr ------------------------------------
345 instance Outputable IfaceExpr where
346 ppr e = pprIfaceExpr noParens e
348 pprIfaceExpr :: (SDoc -> SDoc) -> IfaceExpr -> SDoc
349 -- The function adds parens in context that need
350 -- an atomic value (e.g. function args)
352 pprIfaceExpr add_par (IfaceLcl v) = ppr v
353 pprIfaceExpr add_par (IfaceExt v) = ppr v
354 pprIfaceExpr add_par (IfaceLit l) = ppr l
355 pprIfaceExpr add_par (IfaceFCall cc ty) = braces (ppr cc <+> ppr ty)
356 pprIfaceExpr add_par (IfaceType ty) = char '@' <+> pprParendIfaceType ty
358 pprIfaceExpr add_par app@(IfaceApp _ _) = add_par (pprIfaceApp app [])
359 pprIfaceExpr add_par (IfaceTuple c as) = tupleParens c (interpp'SP as)
361 pprIfaceExpr add_par e@(IfaceLam _ _)
362 = add_par (sep [char '\\' <+> sep (map ppr bndrs) <+> arrow,
363 pprIfaceExpr noParens body])
365 (bndrs,body) = collect [] e
366 collect bs (IfaceLam b e) = collect (b:bs) e
367 collect bs e = (reverse bs, e)
370 pprIfaceExpr add_par (IfaceCase scrut bndr ty [(con, bs, rhs)])
372 = add_par (sep [ptext SLIT("case") <+> char '@' <+> pprParendIfaceType ty <+> pprIfaceExpr noParens scrut <+> ptext SLIT("of")
373 <+> ppr bndr <+> char '{' <+> ppr_con_bs con bs <+> arrow,
374 pprIfaceExpr noParens rhs <+> char '}'])
377 pprIfaceExpr add_par (IfaceCase scrut bndr ty alts)
379 = add_par (sep [ptext SLIT("case") <+> char '@' <+> pprParendIfaceType ty <+> pprIfaceExpr noParens scrut <+> ptext SLIT("of")
380 <+> ppr bndr <+> char '{',
381 nest 2 (sep (map ppr_alt alts)) <+> char '}'])
383 pprIfaceExpr add_par (IfaceLet (IfaceNonRec b rhs) body)
384 = add_par (sep [ptext SLIT("let {"),
385 nest 2 (ppr_bind (b, rhs)),
387 pprIfaceExpr noParens body])
389 pprIfaceExpr add_par (IfaceLet (IfaceRec pairs) body)
390 = add_par (sep [ptext SLIT("letrec {"),
391 nest 2 (sep (map ppr_bind pairs)),
393 pprIfaceExpr noParens body])
395 pprIfaceExpr add_par (IfaceNote note body) = add_par (ppr note <+> pprIfaceExpr parens body)
397 ppr_alt (con, bs, rhs) = sep [ppr_con_bs con bs,
398 arrow <+> pprIfaceExpr noParens rhs]
400 ppr_con_bs (IfaceTupleAlt tup_con) bs = tupleParens tup_con (interpp'SP bs)
401 ppr_con_bs con bs = ppr con <+> hsep (map ppr bs)
403 ppr_bind ((b,ty),rhs) = sep [ppr b <+> dcolon <+> ppr ty,
404 equals <+> pprIfaceExpr noParens rhs]
407 pprIfaceApp (IfaceApp fun arg) args = pprIfaceApp fun (nest 2 (pprIfaceExpr parens arg) : args)
408 pprIfaceApp fun args = sep (pprIfaceExpr parens fun : args)
411 instance Outputable IfaceNote where
412 ppr (IfaceSCC cc) = pprCostCentreCore cc
413 ppr (IfaceCoerce ty) = ptext SLIT("__coerce") <+> pprParendIfaceType ty
414 ppr IfaceInlineCall = ptext SLIT("__inline_call")
415 ppr IfaceInlineMe = ptext SLIT("__inline_me")
416 ppr (IfaceCoreNote s) = ptext SLIT("__core_note") <+> pprHsString (mkFastString s)
418 instance Outputable IfaceConAlt where
419 ppr IfaceDefault = text "DEFAULT"
420 ppr (IfaceLitAlt l) = ppr l
421 ppr (IfaceDataAlt d) = ppr d
422 ppr (IfaceTupleAlt b) = panic "ppr IfaceConAlt"
423 -- IfaceTupleAlt is handled by the case-alternative printer
426 instance Outputable IfaceIdInfo where
428 ppr (HasInfo is) = ptext SLIT("{-") <+> fsep (map ppr_hs_info is) <+> ptext SLIT("-}")
430 ppr_hs_info (HsUnfold unf) = ptext SLIT("Unfolding:") <+>
431 parens (pprIfaceExpr noParens unf)
432 ppr_hs_info (HsInline act) = ptext SLIT("Inline:") <+> ppr act
433 ppr_hs_info (HsArity arity) = ptext SLIT("Arity:") <+> int arity
434 ppr_hs_info (HsStrictness str) = ptext SLIT("Strictness:") <+> pprIfaceStrictSig str
435 ppr_hs_info HsNoCafRefs = ptext SLIT("HasNoCafRefs")
436 ppr_hs_info (HsWorker w a) = ptext SLIT("Worker:") <+> ppr w <+> int a
440 %************************************************************************
442 Converting things to their Iface equivalents
444 %************************************************************************
448 tyThingToIfaceDecl :: (Name -> IfaceExtName) -> TyThing -> IfaceDecl
449 -- Assumption: the thing is already tidied, so that locally-bound names
450 -- (lambdas, for-alls) already have non-clashing OccNames
451 -- Reason: Iface stuff uses OccNames, and the conversion here does
452 -- not do tidying on the way
453 tyThingToIfaceDecl ext (AnId id)
454 = IfaceId { ifName = getOccName id,
455 ifType = toIfaceType ext (idType id),
458 info = case toIfaceIdInfo ext (idInfo id) of
460 items -> HasInfo items
462 tyThingToIfaceDecl ext (AClass clas)
463 = IfaceClass { ifCtxt = toIfaceContext ext sc_theta,
464 ifName = getOccName clas,
465 ifTyVars = toIfaceTvBndrs clas_tyvars,
466 ifFDs = map toIfaceFD clas_fds,
467 ifSigs = map toIfaceClassOp op_stuff,
468 ifRec = boolToRecFlag (isRecursiveTyCon tycon),
469 ifVrcs = tyConArgVrcs tycon }
471 (clas_tyvars, clas_fds, sc_theta, _, op_stuff) = classExtraBigSig clas
472 tycon = classTyCon clas
474 toIfaceClassOp (sel_id, def_meth)
475 = ASSERT(sel_tyvars == clas_tyvars)
476 IfaceClassOp (getOccName sel_id) def_meth (toIfaceType ext op_ty)
478 -- Be careful when splitting the type, because of things
479 -- like class Foo a where
480 -- op :: (?x :: String) => a -> a
481 -- and class Baz a where
482 -- op :: (Ord a) => a -> a
483 (sel_tyvars, rho_ty) = splitForAllTys (idType sel_id)
484 op_ty = funResultTy rho_ty
486 toIfaceFD (tvs1, tvs2) = (map getOccName tvs1, map getOccName tvs2)
488 tyThingToIfaceDecl ext (ATyCon tycon)
490 = IfaceSyn { ifName = getOccName tycon,
491 ifTyVars = toIfaceTvBndrs tyvars,
492 ifVrcs = tyConArgVrcs tycon,
493 ifSynRhs = toIfaceType ext syn_ty }
496 = IfaceData { ifName = getOccName tycon,
497 ifTyVars = toIfaceTvBndrs tyvars,
498 ifCtxt = toIfaceContext ext (tyConStupidTheta tycon),
499 ifCons = ifaceConDecls (algTyConRhs tycon),
500 ifRec = boolToRecFlag (isRecursiveTyCon tycon),
501 ifVrcs = tyConArgVrcs tycon,
502 ifGeneric = tyConHasGenerics tycon }
504 | isForeignTyCon tycon
505 = IfaceForeign { ifName = getOccName tycon,
506 ifExtName = tyConExtName tycon }
508 | isPrimTyCon tycon || isFunTyCon tycon
509 -- Needed in GHCi for ':info Int#', for example
510 = IfaceData { ifName = getOccName tycon,
511 ifTyVars = toIfaceTvBndrs (take (tyConArity tycon) alphaTyVars),
513 ifCons = IfAbstractTyCon,
515 ifRec = NonRecursive,
516 ifVrcs = tyConArgVrcs tycon }
518 | otherwise = pprPanic "toIfaceDecl" (ppr tycon)
520 tyvars = tyConTyVars tycon
521 syn_ty = synTyConRhs tycon
523 ifaceConDecls (NewTyCon { data_con = con }) = IfNewTyCon (ifaceConDecl con)
524 ifaceConDecls (DataTyCon { data_cons = cons }) = IfDataTyCon (map ifaceConDecl cons)
525 ifaceConDecls AbstractTyCon = IfAbstractTyCon
526 -- The last case happens when a TyCon has been trimmed during tidying
527 -- Furthermore, tyThingToIfaceDecl is also used
528 -- in TcRnDriver for GHCi, when browsing a module, in which case the
529 -- AbstractTyCon case is perfectly sensible.
531 ifaceConDecl data_con
532 | isVanillaDataCon data_con
533 = IfVanillaCon {ifConOcc = getOccName (dataConName data_con),
534 ifConInfix = dataConIsInfix data_con,
535 ifConArgTys = map (toIfaceType ext) arg_tys,
536 ifConStricts = strict_marks,
537 ifConFields = map getOccName field_labels }
539 = IfGadtCon { ifConOcc = getOccName (dataConName data_con),
540 ifConTyVars = toIfaceTvBndrs tyvars,
541 ifConCtxt = toIfaceContext ext theta,
542 ifConArgTys = map (toIfaceType ext) arg_tys,
543 ifConResTys = map (toIfaceType ext) res_tys,
544 ifConStricts = strict_marks }
546 (tyvars, theta, arg_tys, _, res_tys) = dataConSig data_con
547 field_labels = dataConFieldLabels data_con
548 strict_marks = dataConStrictMarks data_con
550 tyThingToIfaceDecl ext (ADataCon dc)
551 = pprPanic "toIfaceDecl" (ppr dc) -- Should be trimmed out earlier
554 --------------------------
555 instanceToIfaceInst :: (Name -> IfaceExtName) -> Instance -> IfaceInst
556 instanceToIfaceInst ext_lhs ispec@(Instance { is_dfun = dfun_id, is_flag = oflag,
557 is_cls = cls, is_tcs = mb_tcs,
559 = IfaceInst { ifDFun = getOccName dfun_id,
561 ifInstCls = ext_lhs cls,
562 ifInstTys = map do_rough mb_tcs,
565 do_rough Nothing = Nothing
566 do_rough (Just n) = Just (toIfaceTyCon_name ext_lhs n)
568 --------------------------
569 toIfaceIdInfo :: (Name -> IfaceExtName) -> IdInfo -> [IfaceInfoItem]
570 toIfaceIdInfo ext id_info
571 = catMaybes [arity_hsinfo, caf_hsinfo, strict_hsinfo,
572 inline_hsinfo, wrkr_hsinfo, unfold_hsinfo]
574 ------------ Arity --------------
575 arity_info = arityInfo id_info
576 arity_hsinfo | arity_info == 0 = Nothing
577 | otherwise = Just (HsArity arity_info)
579 ------------ Caf Info --------------
580 caf_info = cafInfo id_info
581 caf_hsinfo = case caf_info of
582 NoCafRefs -> Just HsNoCafRefs
585 ------------ Strictness --------------
586 -- No point in explicitly exporting TopSig
587 strict_hsinfo = case newStrictnessInfo id_info of
588 Just sig | not (isTopSig sig) -> Just (HsStrictness sig)
591 ------------ Worker --------------
592 work_info = workerInfo id_info
593 has_worker = case work_info of { HasWorker _ _ -> True; other -> False }
594 wrkr_hsinfo = case work_info of
595 HasWorker work_id wrap_arity ->
596 Just (HsWorker (ext (idName work_id)) wrap_arity)
599 ------------ Unfolding --------------
600 -- The unfolding is redundant if there is a worker
601 unfold_info = unfoldingInfo id_info
602 rhs = unfoldingTemplate unfold_info
603 no_unfolding = neverUnfold unfold_info
604 -- The CoreTidy phase retains unfolding info iff
605 -- we want to expose the unfolding, taking into account
606 -- unconditional NOINLINE, etc. See TidyPgm.addExternal
607 unfold_hsinfo | no_unfolding = Nothing
608 | has_worker = Nothing -- Unfolding is implicit
609 | otherwise = Just (HsUnfold (toIfaceExpr ext rhs))
611 ------------ Inline prag --------------
612 inline_prag = inlinePragInfo id_info
613 inline_hsinfo | isAlwaysActive inline_prag = Nothing
614 | no_unfolding && not has_worker = Nothing
615 -- If the iface file give no unfolding info, we
616 -- don't need to say when inlining is OK!
617 | otherwise = Just (HsInline inline_prag)
619 --------------------------
620 coreRuleToIfaceRule :: (Name -> IfaceExtName) -- For the LHS names
621 -> (Name -> IfaceExtName) -- For the RHS names
622 -> CoreRule -> IfaceRule
623 coreRuleToIfaceRule ext_lhs ext_rhs (BuiltinRule { ru_fn = fn})
624 = pprTrace "toHsRule: builtin" (ppr fn) $
625 bogusIfaceRule (mkIfaceExtName fn)
627 coreRuleToIfaceRule ext_lhs ext_rhs
628 (Rule { ru_name = name, ru_fn = fn, ru_act = act, ru_bndrs = bndrs,
629 ru_args = args, ru_rhs = rhs, ru_orph = orph })
630 = IfaceRule { ifRuleName = name, ifActivation = act,
631 ifRuleBndrs = map (toIfaceBndr ext_lhs) bndrs,
632 ifRuleHead = ext_lhs fn,
633 ifRuleArgs = map do_arg args,
634 ifRuleRhs = toIfaceExpr ext_rhs rhs,
637 -- For type args we must remove synonyms from the outermost
638 -- level. Reason: so that when we read it back in we'll
639 -- construct the same ru_rough field as we have right now;
641 do_arg (Type ty) = IfaceType (toIfaceType ext_lhs (deNoteType ty))
642 do_arg arg = toIfaceExpr ext_lhs arg
644 bogusIfaceRule :: IfaceExtName -> IfaceRule
645 bogusIfaceRule id_name
646 = IfaceRule { ifRuleName = FSLIT("bogus"), ifActivation = NeverActive,
647 ifRuleBndrs = [], ifRuleHead = id_name, ifRuleArgs = [],
648 ifRuleRhs = IfaceExt id_name, ifRuleOrph = Nothing }
650 ---------------------
651 toIfaceExpr :: (Name -> IfaceExtName) -> CoreExpr -> IfaceExpr
652 toIfaceExpr ext (Var v) = toIfaceVar ext v
653 toIfaceExpr ext (Lit l) = IfaceLit l
654 toIfaceExpr ext (Type ty) = IfaceType (toIfaceType ext ty)
655 toIfaceExpr ext (Lam x b) = IfaceLam (toIfaceBndr ext x) (toIfaceExpr ext b)
656 toIfaceExpr ext (App f a) = toIfaceApp ext f [a]
658 toIfaceExpr ext (Case s x ty as) = IfaceCase (toIfaceExpr ext s) (getOccName x) (toIfaceType ext ty) (map (toIfaceAlt ext) as)
659 toIfaceExpr ext (Let b e) = IfaceLet (toIfaceBind ext b) (toIfaceExpr ext e)
660 toIfaceExpr ext (Note n e) = IfaceNote (toIfaceNote ext n) (toIfaceExpr ext e)
662 ---------------------
663 toIfaceNote ext (SCC cc) = IfaceSCC cc
664 toIfaceNote ext (Coerce t1 _) = IfaceCoerce (toIfaceType ext t1)
665 toIfaceNote ext InlineCall = IfaceInlineCall
666 toIfaceNote ext InlineMe = IfaceInlineMe
667 toIfaceNote ext (CoreNote s) = IfaceCoreNote s
669 ---------------------
670 toIfaceBind ext (NonRec b r) = IfaceNonRec (toIfaceIdBndr ext b) (toIfaceExpr ext r)
671 toIfaceBind ext (Rec prs) = IfaceRec [(toIfaceIdBndr ext b, toIfaceExpr ext r) | (b,r) <- prs]
673 ---------------------
674 toIfaceAlt ext (c,bs,r) = (toIfaceCon c, map getOccName bs, toIfaceExpr ext r)
676 ---------------------
677 toIfaceCon (DataAlt dc) | isTupleTyCon tc = IfaceTupleAlt (tupleTyConBoxity tc)
678 | otherwise = IfaceDataAlt (getOccName dc)
682 toIfaceCon (LitAlt l) = IfaceLitAlt l
683 toIfaceCon DEFAULT = IfaceDefault
685 ---------------------
686 toIfaceApp ext (App f a) as = toIfaceApp ext f (a:as)
687 toIfaceApp ext (Var v) as
688 = case isDataConWorkId_maybe v of
689 -- We convert the *worker* for tuples into IfaceTuples
690 Just dc | isTupleTyCon tc && saturated
691 -> IfaceTuple (tupleTyConBoxity tc) tup_args
693 val_args = dropWhile isTypeArg as
694 saturated = val_args `lengthIs` idArity v
695 tup_args = map (toIfaceExpr ext) val_args
698 other -> mkIfaceApps ext (toIfaceVar ext v) as
700 toIfaceApp ext e as = mkIfaceApps ext (toIfaceExpr ext e) as
702 mkIfaceApps ext f as = foldl (\f a -> IfaceApp f (toIfaceExpr ext a)) f as
704 ---------------------
705 toIfaceVar :: (Name -> IfaceExtName) -> Id -> IfaceExpr
707 | Just fcall <- isFCallId_maybe v = IfaceFCall fcall (toIfaceType ext (idType v))
708 -- Foreign calls have special syntax
709 | isExternalName name = IfaceExt (ext name)
710 | otherwise = IfaceLcl (nameOccName name)
716 %************************************************************************
718 Equality, for interface file version generaion only
720 %************************************************************************
722 Equality over IfaceSyn returns an IfaceEq, not a Bool. The new constructor is
723 EqBut, which gives the set of *locally-defined* things whose version must be equal
724 for the whole thing to be equal. So the key function is eqIfExt, which compares
727 Of course, equality is also done modulo alpha conversion.
731 = Equal -- Definitely exactly the same
732 | NotEqual -- Definitely different
733 | EqBut OccSet -- The same provided these local things have not changed
735 bool :: Bool -> IfaceEq
737 bool False = NotEqual
739 zapEq :: IfaceEq -> IfaceEq -- Used to forget EqBut information
740 zapEq (EqBut _) = Equal
743 (&&&) :: IfaceEq -> IfaceEq -> IfaceEq
745 NotEqual &&& x = NotEqual
746 EqBut occs &&& Equal = EqBut occs
747 EqBut occs &&& NotEqual = NotEqual
748 EqBut occs1 &&& EqBut occs2 = EqBut (occs1 `unionOccSets` occs2)
750 ---------------------
751 eqIfExt :: IfaceExtName -> IfaceExtName -> IfaceEq
752 -- This function is the core of the EqBut stuff
753 eqIfExt (ExtPkg mod1 occ1) (ExtPkg mod2 occ2) = bool (mod1==mod2 && occ1==occ2)
754 eqIfExt (HomePkg mod1 occ1 v1) (HomePkg mod2 occ2 v2) = bool (mod1==mod2 && occ1==occ2 && v1==v2)
755 eqIfExt (LocalTop occ1) (LocalTop occ2) | occ1 == occ2 = EqBut (unitOccSet occ1)
756 eqIfExt (LocalTopSub occ1 p1) (LocalTop occ2) | occ1 == occ2 = EqBut (unitOccSet p1)
757 eqIfExt (LocalTopSub occ1 p1) (LocalTopSub occ2 _) | occ1 == occ2 = EqBut (unitOccSet p1)
758 eqIfExt n1 n2 = NotEqual
763 ---------------------
764 eqIfDecl :: IfaceDecl -> IfaceDecl -> IfaceEq
765 eqIfDecl (IfaceId s1 t1 i1) (IfaceId s2 t2 i2)
766 = bool (s1 == s2) &&& (t1 `eqIfType` t2) &&& (i1 `eqIfIdInfo` i2)
768 eqIfDecl d1@(IfaceForeign {}) d2@(IfaceForeign {})
769 = bool (ifName d1 == ifName d2 && ifExtName d1 == ifExtName d2)
771 eqIfDecl d1@(IfaceData {}) d2@(IfaceData {})
772 = bool (ifName d1 == ifName d2 &&
773 ifRec d1 == ifRec d2 &&
774 ifVrcs d1 == ifVrcs d2 &&
775 ifGeneric d1 == ifGeneric d2) &&&
776 eqWith (ifTyVars d1) (ifTyVars d2) (\ env ->
777 eq_ifContext env (ifCtxt d1) (ifCtxt d2) &&&
778 eq_hsCD env (ifCons d1) (ifCons d2)
780 -- The type variables of the data type do not scope
781 -- over the constructors (any more), but they do scope
782 -- over the stupid context in the IfaceConDecls
784 eqIfDecl d1@(IfaceSyn {}) d2@(IfaceSyn {})
785 = bool (ifName d1 == ifName d2) &&&
786 eqWith (ifTyVars d1) (ifTyVars d2) (\ env ->
787 eq_ifType env (ifSynRhs d1) (ifSynRhs d2)
790 eqIfDecl d1@(IfaceClass {}) d2@(IfaceClass {})
791 = bool (ifName d1 == ifName d2 &&
792 ifRec d1 == ifRec d2 &&
793 ifVrcs d1 == ifVrcs d2) &&&
794 eqWith (ifTyVars d1) (ifTyVars d2) (\ env ->
795 eq_ifContext env (ifCtxt d1) (ifCtxt d2) &&&
796 eqListBy (eq_hsFD env) (ifFDs d1) (ifFDs d2) &&&
797 eqListBy (eq_cls_sig env) (ifSigs d1) (ifSigs d2)
800 eqIfDecl _ _ = NotEqual -- default case
803 eqWith :: [IfaceTvBndr] -> [IfaceTvBndr] -> (EqEnv -> IfaceEq) -> IfaceEq
804 eqWith = eq_ifTvBndrs emptyEqEnv
806 -----------------------
807 eqIfInst d1 d2 = bool (ifDFun d1 == ifDFun d2)
808 -- All other changes are handled via the version info on the dfun
810 eqIfRule (IfaceRule n1 a1 bs1 f1 es1 rhs1 o1)
811 (IfaceRule n2 a2 bs2 f2 es2 rhs2 o2)
812 = bool (n1==n2 && a1==a2 && o1 == o2) &&&
814 eq_ifBndrs emptyEqEnv bs1 bs2 (\env ->
815 zapEq (eqListBy (eq_ifaceExpr env) es1 es2) &&&
816 -- zapEq: for the LHSs, ignore the EqBut part
817 eq_ifaceExpr env rhs1 rhs2)
819 eq_hsCD env (IfDataTyCon c1) (IfDataTyCon c2)
820 = eqListBy (eq_ConDecl env) c1 c2
822 eq_hsCD env (IfNewTyCon c1) (IfNewTyCon c2) = eq_ConDecl env c1 c2
823 eq_hsCD env IfAbstractTyCon IfAbstractTyCon = Equal
824 eq_hsCD env d1 d2 = NotEqual
826 eq_ConDecl env c1@(IfVanillaCon {}) c2@(IfVanillaCon {})
827 = bool (ifConOcc c1 == ifConOcc c2 &&
828 ifConInfix c1 == ifConInfix c2 &&
829 ifConStricts c1 == ifConStricts c2 &&
830 ifConFields c1 == ifConFields c2) &&&
831 eq_ifTypes env (ifConArgTys c1) (ifConArgTys c2)
833 eq_ConDecl env c1@(IfGadtCon {}) c2@(IfGadtCon {})
834 = bool (ifConOcc c1 == ifConOcc c2 &&
835 ifConStricts c1 == ifConStricts c2) &&&
836 eq_ifTvBndrs env (ifConTyVars c1) (ifConTyVars c2) (\ env ->
837 eq_ifContext env (ifConCtxt c1) (ifConCtxt c2) &&&
838 eq_ifTypes env (ifConResTys c1) (ifConResTys c2) &&&
839 eq_ifTypes env (ifConArgTys c1) (ifConArgTys c2))
841 eq_ConDecl env c1 c2 = NotEqual
843 eq_hsFD env (ns1,ms1) (ns2,ms2)
844 = eqListBy (eqIfOcc env) ns1 ns2 &&& eqListBy (eqIfOcc env) ms1 ms2
846 eq_cls_sig env (IfaceClassOp n1 dm1 ty1) (IfaceClassOp n2 dm2 ty2)
847 = bool (n1==n2 && dm1 == dm2) &&& eq_ifType env ty1 ty2
853 eqIfIdInfo NoInfo NoInfo = Equal
854 eqIfIdInfo (HasInfo is1) (HasInfo is2) = eqListBy eq_item is1 is2
855 eqIfIdInfo i1 i2 = NotEqual
857 eq_item (HsInline a1) (HsInline a2) = bool (a1 == a2)
858 eq_item (HsArity a1) (HsArity a2) = bool (a1 == a2)
859 eq_item (HsStrictness s1) (HsStrictness s2) = bool (s1 == s2)
860 eq_item (HsUnfold u1) (HsUnfold u2) = eq_ifaceExpr emptyEqEnv u1 u2
861 eq_item HsNoCafRefs HsNoCafRefs = Equal
862 eq_item (HsWorker wkr1 a1) (HsWorker wkr2 a2) = bool (a1==a2) &&& (wkr1 `eqIfExt` wkr2)
863 eq_item _ _ = NotEqual
866 eq_ifaceExpr :: EqEnv -> IfaceExpr -> IfaceExpr -> IfaceEq
867 eq_ifaceExpr env (IfaceLcl v1) (IfaceLcl v2) = eqIfOcc env v1 v2
868 eq_ifaceExpr env (IfaceExt v1) (IfaceExt v2) = eqIfExt v1 v2
869 eq_ifaceExpr env (IfaceLit l1) (IfaceLit l2) = bool (l1 == l2)
870 eq_ifaceExpr env (IfaceFCall c1 ty1) (IfaceFCall c2 ty2) = bool (c1==c2) &&& eq_ifType env ty1 ty2
871 eq_ifaceExpr env (IfaceType ty1) (IfaceType ty2) = eq_ifType env ty1 ty2
872 eq_ifaceExpr env (IfaceTuple n1 as1) (IfaceTuple n2 as2) = bool (n1==n2) &&& eqListBy (eq_ifaceExpr env) as1 as2
873 eq_ifaceExpr env (IfaceLam b1 body1) (IfaceLam b2 body2) = eq_ifBndr env b1 b2 (\env -> eq_ifaceExpr env body1 body2)
874 eq_ifaceExpr env (IfaceApp f1 a1) (IfaceApp f2 a2) = eq_ifaceExpr env f1 f2 &&& eq_ifaceExpr env a1 a2
875 eq_ifaceExpr env (IfaceNote n1 r1) (IfaceNote n2 r2) = eq_ifaceNote env n1 n2 &&& eq_ifaceExpr env r1 r2
877 eq_ifaceExpr env (IfaceCase s1 b1 ty1 as1) (IfaceCase s2 b2 ty2 as2)
878 = eq_ifaceExpr env s1 s2 &&&
879 eq_ifType env ty1 ty2 &&&
880 eq_ifNakedBndr env b1 b2 (\env -> eqListBy (eq_ifaceAlt env) as1 as2)
882 eq_ifaceAlt env (c1,bs1,r1) (c2,bs2,r2)
883 = bool (eq_ifaceConAlt c1 c2) &&&
884 eq_ifNakedBndrs env bs1 bs2 (\env -> eq_ifaceExpr env r1 r2)
886 eq_ifaceExpr env (IfaceLet (IfaceNonRec b1 r1) x1) (IfaceLet (IfaceNonRec b2 r2) x2)
887 = eq_ifaceExpr env r1 r2 &&& eq_ifIdBndr env b1 b2 (\env -> eq_ifaceExpr env x1 x2)
889 eq_ifaceExpr env (IfaceLet (IfaceRec as1) x1) (IfaceLet (IfaceRec as2) x2)
890 = eq_ifIdBndrs env bs1 bs2 (\env -> eqListBy (eq_ifaceExpr env) rs1 rs2 &&& eq_ifaceExpr env x1 x2)
892 (bs1,rs1) = unzip as1
893 (bs2,rs2) = unzip as2
896 eq_ifaceExpr env _ _ = NotEqual
899 eq_ifaceConAlt :: IfaceConAlt -> IfaceConAlt -> Bool
900 eq_ifaceConAlt IfaceDefault IfaceDefault = True
901 eq_ifaceConAlt (IfaceDataAlt n1) (IfaceDataAlt n2) = n1==n2
902 eq_ifaceConAlt (IfaceTupleAlt c1) (IfaceTupleAlt c2) = c1==c2
903 eq_ifaceConAlt (IfaceLitAlt l1) (IfaceLitAlt l2) = l1==l2
904 eq_ifaceConAlt _ _ = False
907 eq_ifaceNote :: EqEnv -> IfaceNote -> IfaceNote -> IfaceEq
908 eq_ifaceNote env (IfaceSCC c1) (IfaceSCC c2) = bool (c1==c2)
909 eq_ifaceNote env (IfaceCoerce t1) (IfaceCoerce t2) = eq_ifType env t1 t2
910 eq_ifaceNote env IfaceInlineCall IfaceInlineCall = Equal
911 eq_ifaceNote env IfaceInlineMe IfaceInlineMe = Equal
912 eq_ifaceNote env (IfaceCoreNote s1) (IfaceCoreNote s2) = bool (s1==s2)
913 eq_ifaceNote env _ _ = NotEqual
917 ---------------------
918 eqIfType t1 t2 = eq_ifType emptyEqEnv t1 t2
921 eq_ifType env (IfaceTyVar n1) (IfaceTyVar n2) = eqIfOcc env n1 n2
922 eq_ifType env (IfaceAppTy s1 t1) (IfaceAppTy s2 t2) = eq_ifType env s1 s2 &&& eq_ifType env t1 t2
923 eq_ifType env (IfacePredTy st1) (IfacePredTy st2) = eq_ifPredType env st1 st2
924 eq_ifType env (IfaceTyConApp tc1 ts1) (IfaceTyConApp tc2 ts2) = tc1 `eqIfTc` tc2 &&& eq_ifTypes env ts1 ts2
925 eq_ifType env (IfaceForAllTy tv1 t1) (IfaceForAllTy tv2 t2) = eq_ifTvBndr env tv1 tv2 (\env -> eq_ifType env t1 t2)
926 eq_ifType env (IfaceFunTy s1 t1) (IfaceFunTy s2 t2) = eq_ifType env s1 s2 &&& eq_ifType env t1 t2
927 eq_ifType env _ _ = NotEqual
930 eq_ifTypes env = eqListBy (eq_ifType env)
933 eq_ifContext env a b = eqListBy (eq_ifPredType env) a b
936 eq_ifPredType env (IfaceClassP c1 tys1) (IfaceClassP c2 tys2) = c1 `eqIfExt` c2 &&& eq_ifTypes env tys1 tys2
937 eq_ifPredType env (IfaceIParam n1 ty1) (IfaceIParam n2 ty2) = bool (n1 == n2) &&& eq_ifType env ty1 ty2
938 eq_ifPredType env _ _ = NotEqual
941 eqIfTc (IfaceTc tc1) (IfaceTc tc2) = tc1 `eqIfExt` tc2
942 eqIfTc IfaceIntTc IfaceIntTc = Equal
943 eqIfTc IfaceCharTc IfaceCharTc = Equal
944 eqIfTc IfaceBoolTc IfaceBoolTc = Equal
945 eqIfTc IfaceListTc IfaceListTc = Equal
946 eqIfTc IfacePArrTc IfacePArrTc = Equal
947 eqIfTc (IfaceTupTc bx1 ar1) (IfaceTupTc bx2 ar2) = bool (bx1==bx2 && ar1==ar2)
948 eqIfTc _ _ = NotEqual
951 -----------------------------------------------------------
952 Support code for equality checking
953 -----------------------------------------------------------
956 ------------------------------------
957 type EqEnv = OccEnv OccName -- Tracks the mapping from L-variables to R-variables
959 eqIfOcc :: EqEnv -> OccName -> OccName -> IfaceEq
960 eqIfOcc env n1 n2 = case lookupOccEnv env n1 of
961 Just n1 -> bool (n1 == n2)
962 Nothing -> bool (n1 == n2)
964 extendEqEnv :: EqEnv -> OccName -> OccName -> EqEnv
965 extendEqEnv env n1 n2 | n1 == n2 = env
966 | otherwise = extendOccEnv env n1 n2
969 emptyEqEnv = emptyOccEnv
971 ------------------------------------
972 type ExtEnv bndr = EqEnv -> bndr -> bndr -> (EqEnv -> IfaceEq) -> IfaceEq
974 eq_ifNakedBndr :: ExtEnv OccName
975 eq_ifBndr :: ExtEnv IfaceBndr
976 eq_ifTvBndr :: ExtEnv IfaceTvBndr
977 eq_ifIdBndr :: ExtEnv IfaceIdBndr
979 eq_ifNakedBndr env n1 n2 k = k (extendEqEnv env n1 n2)
981 eq_ifBndr env (IfaceIdBndr b1) (IfaceIdBndr b2) k = eq_ifIdBndr env b1 b2 k
982 eq_ifBndr env (IfaceTvBndr b1) (IfaceTvBndr b2) k = eq_ifTvBndr env b1 b2 k
983 eq_ifBndr _ _ _ _ = NotEqual
985 eq_ifTvBndr env (v1, k1) (v2, k2) k = bool (k1 == k2) &&& k (extendEqEnv env v1 v2)
986 eq_ifIdBndr env (v1, t1) (v2, t2) k = eq_ifType env t1 t2 &&& k (extendEqEnv env v1 v2)
988 eq_ifBndrs :: ExtEnv [IfaceBndr]
989 eq_ifIdBndrs :: ExtEnv [IfaceIdBndr]
990 eq_ifTvBndrs :: ExtEnv [IfaceTvBndr]
991 eq_ifNakedBndrs :: ExtEnv [OccName]
992 eq_ifBndrs = eq_bndrs_with eq_ifBndr
993 eq_ifIdBndrs = eq_bndrs_with eq_ifIdBndr
994 eq_ifTvBndrs = eq_bndrs_with eq_ifTvBndr
995 eq_ifNakedBndrs = eq_bndrs_with eq_ifNakedBndr
997 eq_bndrs_with eq env [] [] k = k env
998 eq_bndrs_with eq env (b1:bs1) (b2:bs2) k = eq env b1 b2 (\env -> eq_bndrs_with eq env bs1 bs2 k)
999 eq_bndrs_with eq env _ _ _ = NotEqual
1003 eqListBy :: (a->a->IfaceEq) -> [a] -> [a] -> IfaceEq
1004 eqListBy eq [] [] = Equal
1005 eqListBy eq (x:xs) (y:ys) = eq x y &&& eqListBy eq xs ys
1006 eqListBy eq xs ys = NotEqual
1008 eqMaybeBy :: (a->a->IfaceEq) -> Maybe a -> Maybe a -> IfaceEq
1009 eqMaybeBy eq Nothing Nothing = Equal
1010 eqMaybeBy eq (Just x) (Just y) = eq x y
1011 eqMaybeBy eq x y = NotEqual