module GHC.IfaceToCore (
tcLookupImported_maybe,
importDecl, checkWiredInTyCon, tcHiBootIface, typecheckIface,
typecheckIfacesForMerging,
typecheckIfaceForInstantiate,
tcIfaceDecl, tcIfaceDecls,
tcIfaceInst, tcIfaceFamInst, tcIfaceRules,
tcIfaceAnnotations, tcIfaceCompleteMatches,
tcIfaceExpr,
tcIfaceGlobal,
tcIfaceOneShot
) where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Driver.Env
import GHC.Driver.Session
import GHC.Builtin.Types.Literals(typeNatCoAxiomRules)
import GHC.Builtin.Types
import GHC.Iface.Syntax
import GHC.Iface.Load
import GHC.Iface.Env
import GHC.StgToCmm.Types
import GHC.Tc.TyCl.Build
import GHC.Tc.Utils.Monad
import GHC.Tc.Utils.TcType
import GHC.Core.Type
import GHC.Core.Coercion
import GHC.Core.Coercion.Axiom
import GHC.Core.FVs
import GHC.Core.TyCo.Rep
import GHC.Core.TyCo.Subst ( substTyCoVars )
import GHC.Core.InstEnv
import GHC.Core.FamInstEnv
import GHC.Core
import GHC.Core.Unify( RoughMatchTc(..) )
import GHC.Core.Utils
import GHC.Core.Unfold.Make
import GHC.Core.Lint
import GHC.Core.Make
import GHC.Core.Class
import GHC.Core.TyCon
import GHC.Core.ConLike
import GHC.Core.DataCon
import GHC.Core.Opt.OccurAnal ( occurAnalyseExpr )
import GHC.Core.Ppr
import GHC.Unit.External
import GHC.Unit.Module
import GHC.Unit.Module.ModDetails
import GHC.Unit.Module.ModIface
import GHC.Unit.Home.ModInfo
import GHC.Utils.Outputable
import GHC.Utils.Misc
import GHC.Utils.Panic
import GHC.Utils.Logger
import GHC.Data.Bag
import GHC.Data.Maybe
import GHC.Data.FastString
import GHC.Data.List.SetOps
import GHC.Types.Annotations
import GHC.Types.SourceFile
import GHC.Types.SourceText
import GHC.Types.Basic hiding ( SuccessFlag(..) )
import GHC.Types.CompleteMatch
import GHC.Types.SrcLoc
import GHC.Types.TypeEnv
import GHC.Types.Unique.FM
import GHC.Types.Unique.DSet ( mkUniqDSet )
import GHC.Types.Unique.Supply
import GHC.Types.Literal
import GHC.Types.Var as Var
import GHC.Types.Var.Set
import GHC.Types.Name
import GHC.Types.Name.Env
import GHC.Types.Name.Set
import GHC.Types.Id
import GHC.Types.Id.Make
import GHC.Types.Id.Info
import GHC.Types.Tickish
import GHC.Types.TyThing
import GHC.Fingerprint
import qualified GHC.Data.BooleanFormula as BF
import Control.Monad
import GHC.Parser.Annotation
typecheckIface :: ModIface
-> IfG ModDetails
typecheckIface iface
= initIfaceLcl (mi_semantic_module iface) (text "typecheckIface") (mi_boot iface) $ do
{
ignore_prags <- goptM Opt_IgnoreInterfacePragmas
; names_w_things <- tcIfaceDecls ignore_prags (mi_decls iface)
; let type_env = mkNameEnv names_w_things
; insts <- mapM tcIfaceInst (mi_insts iface)
; fam_insts <- mapM tcIfaceFamInst (mi_fam_insts iface)
; rules <- tcIfaceRules ignore_prags (mi_rules iface)
; anns <- tcIfaceAnnotations (mi_anns iface)
; exports <- ifaceExportNames (mi_exports iface)
; complete_matches <- tcIfaceCompleteMatches (mi_complete_matches iface)
; traceIf (vcat [text "Finished typechecking interface for" <+> ppr (mi_module iface),
text "Type envt:" <+> ppr (map fst names_w_things)])
; return $ ModDetails { md_types = type_env
, md_insts = insts
, md_fam_insts = fam_insts
, md_rules = rules
, md_anns = anns
, md_exports = exports
, md_complete_matches = complete_matches
}
}
isAbstractIfaceDecl :: IfaceDecl -> Bool
isAbstractIfaceDecl IfaceData{ ifCons = IfAbstractTyCon } = True
isAbstractIfaceDecl IfaceClass{ ifBody = IfAbstractClass } = True
isAbstractIfaceDecl IfaceFamily{ ifFamFlav = IfaceAbstractClosedSynFamilyTyCon } = True
isAbstractIfaceDecl _ = False
ifMaybeRoles :: IfaceDecl -> Maybe [Role]
ifMaybeRoles IfaceData { ifRoles = rs } = Just rs
ifMaybeRoles IfaceSynonym { ifRoles = rs } = Just rs
ifMaybeRoles IfaceClass { ifRoles = rs } = Just rs
ifMaybeRoles _ = Nothing
mergeIfaceDecl :: IfaceDecl -> IfaceDecl -> IfaceDecl
mergeIfaceDecl d1 d2
| isAbstractIfaceDecl d1 = d2 `withRolesFrom` d1
| isAbstractIfaceDecl d2 = d1 `withRolesFrom` d2
| IfaceClass{ ifBody = IfConcreteClass { ifSigs = ops1, ifMinDef = bf1 } } <- d1
, IfaceClass{ ifBody = IfConcreteClass { ifSigs = ops2, ifMinDef = bf2 } } <- d2
= let ops = nameEnvElts $
plusNameEnv_C mergeIfaceClassOp
(mkNameEnv [ (n, op) | op@(IfaceClassOp n _ _) <- ops1 ])
(mkNameEnv [ (n, op) | op@(IfaceClassOp n _ _) <- ops2 ])
in d1 { ifBody = (ifBody d1) {
ifSigs = ops,
ifMinDef = BF.mkOr [noLocA bf1, noLocA bf2]
}
} `withRolesFrom` d2
| otherwise = d1 `withRolesFrom` d2
withRolesFrom :: IfaceDecl -> IfaceDecl -> IfaceDecl
d1 `withRolesFrom` d2
| Just roles1 <- ifMaybeRoles d1
, Just roles2 <- ifMaybeRoles d2
, not (isRepInjectiveIfaceDecl d1 || isRepInjectiveIfaceDecl d2)
= d1 { ifRoles = mergeRoles roles1 roles2 }
| otherwise = d1
where
mergeRoles roles1 roles2 = zipWithEqual "mergeRoles" max roles1 roles2
isRepInjectiveIfaceDecl :: IfaceDecl -> Bool
isRepInjectiveIfaceDecl IfaceData{ ifCons = IfDataTyCon _ } = True
isRepInjectiveIfaceDecl IfaceFamily{ ifFamFlav = IfaceDataFamilyTyCon } = True
isRepInjectiveIfaceDecl _ = False
mergeIfaceClassOp :: IfaceClassOp -> IfaceClassOp -> IfaceClassOp
mergeIfaceClassOp op1@(IfaceClassOp _ _ (Just _)) _ = op1
mergeIfaceClassOp _ op2 = op2
mergeIfaceDecls :: OccEnv IfaceDecl -> OccEnv IfaceDecl -> OccEnv IfaceDecl
mergeIfaceDecls = plusOccEnv_C mergeIfaceDecl
typecheckIfacesForMerging :: Module -> [ModIface] -> IORef TypeEnv -> IfM lcl (TypeEnv, [ModDetails])
typecheckIfacesForMerging mod ifaces tc_env_var =
initIfaceLcl mod (text "typecheckIfacesForMerging") NotBoot $ do
ignore_prags <- goptM Opt_IgnoreInterfacePragmas
let mk_decl_env decls
= mkOccEnv [ (getOccName decl, decl)
| decl <- decls
, case decl of
IfaceId { ifIdDetails = IfDFunId } -> False
_ -> True ]
decl_envs = map (mk_decl_env . map snd . mi_decls) ifaces
:: [OccEnv IfaceDecl]
decl_env = foldl' mergeIfaceDecls emptyOccEnv decl_envs
:: OccEnv IfaceDecl
names_w_things <- tcIfaceDecls ignore_prags (map (\x -> (fingerprint0, x))
(occEnvElts decl_env))
let global_type_env = mkNameEnv names_w_things
writeMutVar tc_env_var global_type_env
details <- forM ifaces $ \iface -> do
type_env <- fixM $ \type_env ->
setImplicitEnvM type_env $ do
decls <- tcIfaceDecls ignore_prags (mi_decls iface)
return (mkNameEnv decls)
setImplicitEnvM type_env $ do
insts <- mapM tcIfaceInst (mi_insts iface)
fam_insts <- mapM tcIfaceFamInst (mi_fam_insts iface)
rules <- tcIfaceRules ignore_prags (mi_rules iface)
anns <- tcIfaceAnnotations (mi_anns iface)
exports <- ifaceExportNames (mi_exports iface)
complete_matches <- tcIfaceCompleteMatches (mi_complete_matches iface)
return $ ModDetails { md_types = type_env
, md_insts = insts
, md_fam_insts = fam_insts
, md_rules = rules
, md_anns = anns
, md_exports = exports
, md_complete_matches = complete_matches
}
return (global_type_env, details)
typecheckIfaceForInstantiate :: NameShape -> ModIface -> IfM lcl ModDetails
typecheckIfaceForInstantiate nsubst iface =
initIfaceLclWithSubst (mi_semantic_module iface)
(text "typecheckIfaceForInstantiate")
(mi_boot iface) nsubst $ do
ignore_prags <- goptM Opt_IgnoreInterfacePragmas
type_env <- fixM $ \type_env ->
setImplicitEnvM type_env $ do
decls <- tcIfaceDecls ignore_prags (mi_decls iface)
return (mkNameEnv decls)
setImplicitEnvM type_env $ do
insts <- mapM tcIfaceInst (mi_insts iface)
fam_insts <- mapM tcIfaceFamInst (mi_fam_insts iface)
rules <- tcIfaceRules ignore_prags (mi_rules iface)
anns <- tcIfaceAnnotations (mi_anns iface)
exports <- ifaceExportNames (mi_exports iface)
complete_matches <- tcIfaceCompleteMatches (mi_complete_matches iface)
return $ ModDetails { md_types = type_env
, md_insts = insts
, md_fam_insts = fam_insts
, md_rules = rules
, md_anns = anns
, md_exports = exports
, md_complete_matches = complete_matches
}
tcHiBootIface :: HscSource -> Module -> TcRn SelfBootInfo
tcHiBootIface hsc_src mod
| HsBootFile <- hsc_src
= return NoSelfBoot
| otherwise
= do { traceIf (text "loadHiBootInterface" <+> ppr mod)
; mode <- getGhcMode
; if not (isOneShot mode)
then do { hpt <- getHpt
; case lookupHpt hpt (moduleName mod) of
Just info | mi_boot (hm_iface info) == IsBoot
-> mkSelfBootInfo (hm_iface info) (hm_details info)
_ -> return NoSelfBoot }
else do
{ read_result <- findAndReadIface
need (fst (getModuleInstantiation mod)) mod
IsBoot
; case read_result of {
Succeeded (iface, _path) -> do { tc_iface <- initIfaceTcRn $ typecheckIface iface
; mkSelfBootInfo iface tc_iface } ;
Failed err ->
do { eps <- getEps
; case lookupUFM (eps_is_boot eps) (moduleName mod) of
Nothing -> return NoSelfBoot
Just (GWIB { gwib_isBoot = is_boot }) -> case is_boot of
IsBoot -> failWithTc (elaborate err)
NotBoot -> failWithTc moduleLoop
}}}}
where
need = text "Need the hi-boot interface for" <+> ppr mod
<+> text "to compare against the Real Thing"
moduleLoop = text "Circular imports: module" <+> quotes (ppr mod)
<+> text "depends on itself"
elaborate err = hang (text "Could not find hi-boot interface for" <+>
quotes (ppr mod) <> colon) 4 err
mkSelfBootInfo :: ModIface -> ModDetails -> TcRn SelfBootInfo
mkSelfBootInfo iface mds
= do
let tcs = map ifName
. filter isIfaceTyCon
. map snd
$ mi_decls iface
return $ SelfBoot { sb_mds = mds
, sb_tcs = mkNameSet tcs }
where
isIfaceTyCon IfaceId{} = False
isIfaceTyCon IfaceData{} = True
isIfaceTyCon IfaceSynonym{} = True
isIfaceTyCon IfaceFamily{} = True
isIfaceTyCon IfaceClass{} = True
isIfaceTyCon IfaceAxiom{} = False
isIfaceTyCon IfacePatSyn{} = False
tcIfaceDecl :: Bool
-> IfaceDecl
-> IfL TyThing
tcIfaceDecl = tc_iface_decl Nothing
tc_iface_decl :: Maybe Class
-> Bool
-> IfaceDecl
-> IfL TyThing
tc_iface_decl _ ignore_prags (IfaceId {ifName = name, ifType = iface_type,
ifIdDetails = details, ifIdInfo = info})
= do { ty <- tcIfaceType iface_type
; details <- tcIdDetails ty details
; info <- tcIdInfo ignore_prags TopLevel name ty info
; return (AnId (mkGlobalId details name ty info)) }
tc_iface_decl _ _ (IfaceData {ifName = tc_name,
ifCType = cType,
ifBinders = binders,
ifResKind = res_kind,
ifRoles = roles,
ifCtxt = ctxt, ifGadtSyntax = gadt_syn,
ifCons = rdr_cons,
ifParent = mb_parent })
= bindIfaceTyConBinders_AT binders $ \ binders' -> do
{ res_kind' <- tcIfaceType res_kind
; tycon <- fixM $ \ tycon -> do
{ stupid_theta <- tcIfaceCtxt ctxt
; parent' <- tc_parent tc_name mb_parent
; cons <- tcIfaceDataCons tc_name tycon binders' rdr_cons
; return (mkAlgTyCon tc_name binders' res_kind'
roles cType stupid_theta
cons parent' gadt_syn) }
; traceIf (text "tcIfaceDecl4" <+> ppr tycon)
; return (ATyCon tycon) }
where
tc_parent :: Name -> IfaceTyConParent -> IfL AlgTyConFlav
tc_parent tc_name IfNoParent
= do { tc_rep_name <- newTyConRepName tc_name
; return (VanillaAlgTyCon tc_rep_name) }
tc_parent _ (IfDataInstance ax_name _ arg_tys)
= do { ax <- tcIfaceCoAxiom ax_name
; let fam_tc = coAxiomTyCon ax
ax_unbr = toUnbranchedAxiom ax
; lhs_tys <- tcIfaceAppArgs arg_tys
; return (DataFamInstTyCon ax_unbr fam_tc lhs_tys) }
tc_iface_decl _ _ (IfaceSynonym {ifName = tc_name,
ifRoles = roles,
ifSynRhs = rhs_ty,
ifBinders = binders,
ifResKind = res_kind })
= bindIfaceTyConBinders_AT binders $ \ binders' -> do
{ res_kind' <- tcIfaceType res_kind
; rhs <- forkM (mk_doc tc_name) $
tcIfaceType rhs_ty
; let tycon = buildSynTyCon tc_name binders' res_kind' roles rhs
; return (ATyCon tycon) }
where
mk_doc n = text "Type synonym" <+> ppr n
tc_iface_decl parent _ (IfaceFamily {ifName = tc_name,
ifFamFlav = fam_flav,
ifBinders = binders,
ifResKind = res_kind,
ifResVar = res, ifFamInj = inj })
= bindIfaceTyConBinders_AT binders $ \ binders' -> do
{ res_kind' <- tcIfaceType res_kind
; rhs <- forkM (mk_doc tc_name) $
tc_fam_flav tc_name fam_flav
; res_name <- traverse (newIfaceName . mkTyVarOccFS) res
; let tycon = mkFamilyTyCon tc_name binders' res_kind' res_name rhs parent inj
; return (ATyCon tycon) }
where
mk_doc n = text "Type synonym" <+> ppr n
tc_fam_flav :: Name -> IfaceFamTyConFlav -> IfL FamTyConFlav
tc_fam_flav tc_name IfaceDataFamilyTyCon
= do { tc_rep_name <- newTyConRepName tc_name
; return (DataFamilyTyCon tc_rep_name) }
tc_fam_flav _ IfaceOpenSynFamilyTyCon= return OpenSynFamilyTyCon
tc_fam_flav _ (IfaceClosedSynFamilyTyCon mb_ax_name_branches)
= do { ax <- traverse (tcIfaceCoAxiom . fst) mb_ax_name_branches
; return (ClosedSynFamilyTyCon ax) }
tc_fam_flav _ IfaceAbstractClosedSynFamilyTyCon
= return AbstractClosedSynFamilyTyCon
tc_fam_flav _ IfaceBuiltInSynFamTyCon
= pprPanic "tc_iface_decl"
(text "IfaceBuiltInSynFamTyCon in interface file")
tc_iface_decl _parent _ignore_prags
(IfaceClass {ifName = tc_name,
ifRoles = roles,
ifBinders = binders,
ifFDs = rdr_fds,
ifBody = IfAbstractClass})
= bindIfaceTyConBinders binders $ \ binders' -> do
{ fds <- mapM tc_fd rdr_fds
; cls <- buildClass tc_name binders' roles fds Nothing
; return (ATyCon (classTyCon cls)) }
tc_iface_decl _parent ignore_prags
(IfaceClass {ifName = tc_name,
ifRoles = roles,
ifBinders = binders,
ifFDs = rdr_fds,
ifBody = IfConcreteClass {
ifClassCtxt = rdr_ctxt,
ifATs = rdr_ats, ifSigs = rdr_sigs,
ifMinDef = mindef_occ
}})
= bindIfaceTyConBinders binders $ \ binders' -> do
{ traceIf (text "tc-iface-class1" <+> ppr tc_name)
; ctxt <- mapM tc_sc rdr_ctxt
; traceIf (text "tc-iface-class2" <+> ppr tc_name)
; sigs <- mapM tc_sig rdr_sigs
; fds <- mapM tc_fd rdr_fds
; traceIf (text "tc-iface-class3" <+> ppr tc_name)
; mindef <- traverse (lookupIfaceTop . mkVarOccFS) mindef_occ
; cls <- fixM $ \ cls -> do
{ ats <- mapM (tc_at cls) rdr_ats
; traceIf (text "tc-iface-class4" <+> ppr tc_name)
; buildClass tc_name binders' roles fds (Just (ctxt, ats, sigs, mindef)) }
; return (ATyCon (classTyCon cls)) }
where
tc_sc pred = forkM (mk_sc_doc pred) (tcIfaceType pred)
tc_sig :: IfaceClassOp -> IfL TcMethInfo
tc_sig (IfaceClassOp op_name rdr_ty dm)
= do { let doc = mk_op_doc op_name rdr_ty
; op_ty <- forkM (doc <+> text "ty") $ tcIfaceType rdr_ty
; dm' <- tc_dm doc dm
; return (op_name, op_ty, dm') }
tc_dm :: SDoc
-> Maybe (DefMethSpec IfaceType)
-> IfL (Maybe (DefMethSpec (SrcSpan, Type)))
tc_dm _ Nothing = return Nothing
tc_dm _ (Just VanillaDM) = return (Just VanillaDM)
tc_dm doc (Just (GenericDM ty))
= do {
; ty' <- forkM (doc <+> text "dm") $ tcIfaceType ty
; return (Just (GenericDM (noSrcSpan, ty'))) }
tc_at cls (IfaceAT tc_decl if_def)
= do ATyCon tc <- tc_iface_decl (Just cls) ignore_prags tc_decl
mb_def <- case if_def of
Nothing -> return Nothing
Just def -> forkM (mk_at_doc tc) $
extendIfaceTyVarEnv (tyConTyVars tc) $
do { tc_def <- tcIfaceType def
; return (Just (tc_def, NoATVI)) }
return (ATI tc mb_def)
mk_sc_doc pred = text "Superclass" <+> ppr pred
mk_at_doc tc = text "Associated type" <+> ppr tc
mk_op_doc op_name op_ty = text "Class op" <+> sep [ppr op_name, ppr op_ty]
tc_iface_decl _ _ (IfaceAxiom { ifName = tc_name, ifTyCon = tc
, ifAxBranches = branches, ifRole = role })
= do { tc_tycon <- tcIfaceTyCon tc
; tc_branches <- forkM (text "Axiom branches" <+> ppr tc_name)
$ tc_ax_branches branches
; let axiom = CoAxiom { co_ax_unique = nameUnique tc_name
, co_ax_name = tc_name
, co_ax_tc = tc_tycon
, co_ax_role = role
, co_ax_branches = manyBranches tc_branches
, co_ax_implicit = False }
; return (ACoAxiom axiom) }
tc_iface_decl _ _ (IfacePatSyn{ ifName = name
, ifPatMatcher = if_matcher
, ifPatBuilder = if_builder
, ifPatIsInfix = is_infix
, ifPatUnivBndrs = univ_bndrs
, ifPatExBndrs = ex_bndrs
, ifPatProvCtxt = prov_ctxt
, ifPatReqCtxt = req_ctxt
, ifPatArgs = args
, ifPatTy = pat_ty
, ifFieldLabels = field_labels })
= do { traceIf (text "tc_iface_decl" <+> ppr name)
; matcher <- tc_pr if_matcher
; builder <- fmapMaybeM tc_pr if_builder
; bindIfaceForAllBndrs univ_bndrs $ \univ_tvs -> do
{ bindIfaceForAllBndrs ex_bndrs $ \ex_tvs -> do
{ patsyn <- forkM (mk_doc name) $
do { prov_theta <- tcIfaceCtxt prov_ctxt
; req_theta <- tcIfaceCtxt req_ctxt
; pat_ty <- tcIfaceType pat_ty
; arg_tys <- mapM tcIfaceType args
; return $ buildPatSyn name is_infix matcher builder
(univ_tvs, req_theta)
(ex_tvs, prov_theta)
arg_tys pat_ty field_labels }
; return $ AConLike . PatSynCon $ patsyn }}}
where
mk_doc n = text "Pattern synonym" <+> ppr n
tc_pr :: (IfExtName, Bool) -> IfL (Name, Type, Bool)
tc_pr (nm, b) = do { id <- forkM (ppr nm) (tcIfaceExtId nm)
; return (nm, idType id, b) }
tcIfaceDecls :: Bool
-> [(Fingerprint, IfaceDecl)]
-> IfL [(Name,TyThing)]
tcIfaceDecls ignore_prags ver_decls
= concatMapM (tc_iface_decl_fingerprint ignore_prags) ver_decls
tc_iface_decl_fingerprint :: Bool
-> (Fingerprint, IfaceDecl)
-> IfL [(Name,TyThing)]
tc_iface_decl_fingerprint ignore_prags (_version, decl)
= do {
let main_name = ifName decl
; thing <- forkM doc $ do { bumpDeclStats main_name
; tcIfaceDecl ignore_prags decl }
; let mini_env = mkOccEnv [(getOccName t, t) | t <- implicitTyThings thing]
lookup n = case lookupOccEnv mini_env (getOccName n) of
Just thing -> thing
Nothing ->
pprPanic "tc_iface_decl_fingerprint" (ppr main_name <+> ppr n $$ ppr (decl))
; implicit_names <- mapM lookupIfaceTop (ifaceDeclImplicitBndrs decl)
; return $ (main_name, thing) :
[(n, lookup n) | n <- implicit_names]
}
where
doc = text "Declaration for" <+> ppr (ifName decl)
bumpDeclStats :: Name -> IfL ()
bumpDeclStats name
= do { traceIf (text "Loading decl for" <+> ppr name)
; updateEps_ (\eps -> let stats = eps_stats eps
in eps { eps_stats = stats { n_decls_out = n_decls_out stats + 1 } })
}
tc_fd :: FunDep IfLclName -> IfL (FunDep TyVar)
tc_fd (tvs1, tvs2) = do { tvs1' <- mapM tcIfaceTyVar tvs1
; tvs2' <- mapM tcIfaceTyVar tvs2
; return (tvs1', tvs2') }
tc_ax_branches :: [IfaceAxBranch] -> IfL [CoAxBranch]
tc_ax_branches if_branches = foldlM tc_ax_branch [] if_branches
tc_ax_branch :: [CoAxBranch] -> IfaceAxBranch -> IfL [CoAxBranch]
tc_ax_branch prev_branches
(IfaceAxBranch { ifaxbTyVars = tv_bndrs
, ifaxbEtaTyVars = eta_tv_bndrs
, ifaxbCoVars = cv_bndrs
, ifaxbLHS = lhs, ifaxbRHS = rhs
, ifaxbRoles = roles, ifaxbIncomps = incomps })
= bindIfaceTyConBinders_AT
(map (\b -> Bndr (IfaceTvBndr b) (NamedTCB Inferred)) tv_bndrs) $ \ tvs ->
bindIfaceIds cv_bndrs $ \ cvs -> do
{ tc_lhs <- tcIfaceAppArgs lhs
; tc_rhs <- tcIfaceType rhs
; eta_tvs <- bindIfaceTyVars eta_tv_bndrs return
; this_mod <- getIfModule
; let loc = mkGeneralSrcSpan (fsLit "module " `appendFS`
moduleNameFS (moduleName this_mod))
br = CoAxBranch { cab_loc = loc
, cab_tvs = binderVars tvs
, cab_eta_tvs = eta_tvs
, cab_cvs = cvs
, cab_lhs = tc_lhs
, cab_roles = roles
, cab_rhs = tc_rhs
, cab_incomps = map (prev_branches `getNth`) incomps }
; return (prev_branches ++ [br]) }
tcIfaceDataCons :: Name -> TyCon -> [TyConBinder] -> IfaceConDecls -> IfL AlgTyConRhs
tcIfaceDataCons tycon_name tycon tc_tybinders if_cons
= case if_cons of
IfAbstractTyCon -> return AbstractTyCon
IfDataTyCon cons -> do { data_cons <- mapM tc_con_decl cons
; return (mkDataTyConRhs data_cons) }
IfNewTyCon con -> do { data_con <- tc_con_decl con
; mkNewTyConRhs tycon_name tycon data_con }
where
univ_tvs :: [TyVar]
univ_tvs = binderVars tc_tybinders
tag_map :: NameEnv ConTag
tag_map = mkTyConTagMap tycon
tc_con_decl (IfCon { ifConInfix = is_infix,
ifConExTCvs = ex_bndrs,
ifConUserTvBinders = user_bndrs,
ifConName = dc_name,
ifConCtxt = ctxt, ifConEqSpec = spec,
ifConArgTys = args, ifConFields = lbl_names,
ifConStricts = if_stricts,
ifConSrcStricts = if_src_stricts})
=
bindIfaceBndrs ex_bndrs $ \ ex_tvs -> do
{ traceIf (text "Start interface-file tc_con_decl" <+> ppr dc_name)
; user_tv_bndrs <- mapM (\(Bndr bd vis) ->
case bd of
IfaceIdBndr (_, name, _) ->
Bndr <$> tcIfaceLclId name <*> pure vis
IfaceTvBndr (name, _) ->
Bndr <$> tcIfaceTyVar name <*> pure vis)
user_bndrs
; ~(eq_spec, theta, arg_tys, stricts) <- forkM (mk_doc dc_name) $
do { eq_spec <- tcIfaceEqSpec spec
; theta <- tcIfaceCtxt ctxt
; arg_tys <- forkM (mk_doc dc_name <+> text "arg_tys")
$ mapM (\(w, ty) -> mkScaled <$> tcIfaceType w <*> tcIfaceType ty) args
; stricts <- mapM tc_strict if_stricts
; return (eq_spec, theta, arg_tys, stricts) }
; let orig_res_ty = mkFamilyTyConApp tycon
(substTyCoVars (mkTvSubstPrs (map eqSpecPair eq_spec))
(binderVars tc_tybinders))
; prom_rep_name <- newTyConRepName dc_name
; con <- buildDataCon (pprPanic "tcIfaceDataCons: FamInstEnvs" (ppr dc_name))
dc_name is_infix prom_rep_name
(map src_strict if_src_stricts)
(Just stricts)
lbl_names
univ_tvs ex_tvs user_tv_bndrs
eq_spec theta
arg_tys orig_res_ty tycon tag_map
; traceIf (text "Done interface-file tc_con_decl" <+> ppr dc_name)
; return con }
mk_doc con_name = text "Constructor" <+> ppr con_name
tc_strict :: IfaceBang -> IfL HsImplBang
tc_strict IfNoBang = return (HsLazy)
tc_strict IfStrict = return (HsStrict)
tc_strict IfUnpack = return (HsUnpack Nothing)
tc_strict (IfUnpackCo if_co) = do { co <- tcIfaceCo if_co
; return (HsUnpack (Just co)) }
src_strict :: IfaceSrcBang -> HsSrcBang
src_strict (IfSrcBang unpk bang) = HsSrcBang NoSourceText unpk bang
tcIfaceEqSpec :: IfaceEqSpec -> IfL [EqSpec]
tcIfaceEqSpec spec
= mapM do_item spec
where
do_item (occ, if_ty) = do { tv <- tcIfaceTyVar occ
; ty <- tcIfaceType if_ty
; return (mkEqSpec tv ty) }
tcRoughTyCon :: Maybe IfaceTyCon -> RoughMatchTc
tcRoughTyCon (Just tc) = KnownTc (ifaceTyConName tc)
tcRoughTyCon Nothing = OtherTc
tcIfaceInst :: IfaceClsInst -> IfL ClsInst
tcIfaceInst (IfaceClsInst { ifDFun = dfun_name, ifOFlag = oflag
, ifInstCls = cls, ifInstTys = mb_tcs
, ifInstOrph = orph })
= do { dfun <- forkM (text "Dict fun" <+> ppr dfun_name) $
fmap tyThingId (tcIfaceImplicit dfun_name)
; let mb_tcs' = map tcRoughTyCon mb_tcs
; return (mkImportedInstance cls mb_tcs' dfun_name dfun oflag orph) }
tcIfaceFamInst :: IfaceFamInst -> IfL FamInst
tcIfaceFamInst (IfaceFamInst { ifFamInstFam = fam, ifFamInstTys = mb_tcs
, ifFamInstAxiom = axiom_name } )
= do { axiom' <- forkM (text "Axiom" <+> ppr axiom_name) $
tcIfaceCoAxiom axiom_name
; let axiom'' = toUnbranchedAxiom axiom'
mb_tcs' = map tcRoughTyCon mb_tcs
; return (mkImportedFamInst fam mb_tcs' axiom'') }
tcIfaceRules :: Bool
-> [IfaceRule]
-> IfL [CoreRule]
tcIfaceRules ignore_prags if_rules
| ignore_prags = return []
| otherwise = mapM tcIfaceRule if_rules
tcIfaceRule :: IfaceRule -> IfL CoreRule
tcIfaceRule (IfaceRule {ifRuleName = name, ifActivation = act, ifRuleBndrs = bndrs,
ifRuleHead = fn, ifRuleArgs = args, ifRuleRhs = rhs,
ifRuleAuto = auto, ifRuleOrph = orph })
= do { ~(bndrs', args', rhs') <-
forkM (text "Rule" <+> pprRuleName name) $
bindIfaceBndrs bndrs $ \ bndrs' ->
do { args' <- mapM tcIfaceExpr args
; rhs' <- tcIfaceExpr rhs
; whenGOptM Opt_DoCoreLinting $ do
{ dflags <- getDynFlags
; (_, lcl_env) <- getEnvs
; let in_scope :: [Var]
in_scope = ((nonDetEltsUFM $ if_tv_env lcl_env) ++
(nonDetEltsUFM $ if_id_env lcl_env) ++
bndrs' ++
exprsFreeIdsList args')
; case lintExpr dflags in_scope rhs' of
Nothing -> return ()
Just errs -> do
logger <- getLogger
liftIO $ displayLintResults logger dflags False doc
(pprCoreExpr rhs')
(emptyBag, errs) }
; return (bndrs', args', rhs') }
; let mb_tcs = map ifTopFreeName args
; this_mod <- getIfModule
; return (Rule { ru_name = name, ru_fn = fn, ru_act = act,
ru_bndrs = bndrs', ru_args = args',
ru_rhs = occurAnalyseExpr rhs',
ru_rough = mb_tcs,
ru_origin = this_mod,
ru_orphan = orph,
ru_auto = auto,
ru_local = False }) }
where
ifTopFreeName :: IfaceExpr -> Maybe Name
ifTopFreeName (IfaceType (IfaceTyConApp tc _ )) = Just (ifaceTyConName tc)
ifTopFreeName (IfaceType (IfaceTupleTy s _ ts)) = Just (tupleTyConName s (length (appArgsIfaceTypes ts)))
ifTopFreeName (IfaceApp f _) = ifTopFreeName f
ifTopFreeName (IfaceExt n) = Just n
ifTopFreeName _ = Nothing
doc = text "Unfolding of" <+> ppr name
tcIfaceAnnotations :: [IfaceAnnotation] -> IfL [Annotation]
tcIfaceAnnotations = mapM tcIfaceAnnotation
tcIfaceAnnotation :: IfaceAnnotation -> IfL Annotation
tcIfaceAnnotation (IfaceAnnotation target serialized) = do
target' <- tcIfaceAnnTarget target
return $ Annotation {
ann_target = target',
ann_value = serialized
}
tcIfaceAnnTarget :: IfaceAnnTarget -> IfL (AnnTarget Name)
tcIfaceAnnTarget (NamedTarget occ) =
NamedTarget <$> lookupIfaceTop occ
tcIfaceAnnTarget (ModuleTarget mod) =
return $ ModuleTarget mod
tcIfaceCompleteMatches :: [IfaceCompleteMatch] -> IfL [CompleteMatch]
tcIfaceCompleteMatches = mapM tcIfaceCompleteMatch
tcIfaceCompleteMatch :: IfaceCompleteMatch -> IfL CompleteMatch
tcIfaceCompleteMatch (IfaceCompleteMatch ms mtc) = do
conlikes <- mkUniqDSet <$> mapM (forkM doc . tcIfaceConLike) ms
mtc' <- traverse tcIfaceTyCon mtc
return (CompleteMatch conlikes mtc')
where
doc = text "COMPLETE sig" <+> ppr ms
tcIfaceType :: IfaceType -> IfL Type
tcIfaceType = go
where
go (IfaceTyVar n) = TyVarTy <$> tcIfaceTyVar n
go (IfaceFreeTyVar n) = pprPanic "tcIfaceType:IfaceFreeTyVar" (ppr n)
go (IfaceLitTy l) = LitTy <$> tcIfaceTyLit l
go (IfaceFunTy flag w t1 t2) = FunTy flag <$> tcIfaceType w <*> go t1 <*> go t2
go (IfaceTupleTy s i tks) = tcIfaceTupleTy s i tks
go (IfaceAppTy t ts)
= do { t' <- go t
; ts' <- traverse go (appArgsIfaceTypes ts)
; pure (foldl' AppTy t' ts') }
go (IfaceTyConApp tc tks)
= do { tc' <- tcIfaceTyCon tc
; tks' <- mapM go (appArgsIfaceTypes tks)
; return (mkTyConApp tc' tks') }
go (IfaceForAllTy bndr t)
= bindIfaceForAllBndr bndr $ \ tv' vis ->
ForAllTy (Bndr tv' vis) <$> go t
go (IfaceCastTy ty co) = CastTy <$> go ty <*> tcIfaceCo co
go (IfaceCoercionTy co) = CoercionTy <$> tcIfaceCo co
tcIfaceTupleTy :: TupleSort -> PromotionFlag -> IfaceAppArgs -> IfL Type
tcIfaceTupleTy sort is_promoted args
= do { args' <- tcIfaceAppArgs args
; let arity = length args'
; base_tc <- tcTupleTyCon True sort arity
; case is_promoted of
NotPromoted
-> return (mkTyConApp base_tc args')
IsPromoted
-> do { let tc = promoteDataCon (tyConSingleDataCon base_tc)
kind_args = map typeKind args'
; return (mkTyConApp tc (kind_args ++ args')) } }
tcTupleTyCon :: Bool
-> TupleSort
-> Arity
-> IfL TyCon
tcTupleTyCon in_type sort arity
= case sort of
ConstraintTuple -> return (cTupleTyCon arity)
BoxedTuple -> return (tupleTyCon Boxed arity)
UnboxedTuple -> return (tupleTyCon Unboxed arity')
where arity' | in_type = arity `div` 2
| otherwise = arity
tcIfaceAppArgs :: IfaceAppArgs -> IfL [Type]
tcIfaceAppArgs = mapM tcIfaceType . appArgsIfaceTypes
tcIfaceCtxt :: IfaceContext -> IfL ThetaType
tcIfaceCtxt sts = mapM tcIfaceType sts
tcIfaceTyLit :: IfaceTyLit -> IfL TyLit
tcIfaceTyLit (IfaceNumTyLit n) = return (NumTyLit n)
tcIfaceTyLit (IfaceStrTyLit n) = return (StrTyLit n)
tcIfaceTyLit (IfaceCharTyLit n) = return (CharTyLit n)
tcIfaceCo :: IfaceCoercion -> IfL Coercion
tcIfaceCo = go
where
go_mco IfaceMRefl = pure MRefl
go_mco (IfaceMCo co) = MCo <$> (go co)
go (IfaceReflCo t) = Refl <$> tcIfaceType t
go (IfaceGReflCo r t mco) = GRefl r <$> tcIfaceType t <*> go_mco mco
go (IfaceFunCo r w c1 c2) = mkFunCo r <$> go w <*> go c1 <*> go c2
go (IfaceTyConAppCo r tc cs)
= TyConAppCo r <$> tcIfaceTyCon tc <*> mapM go cs
go (IfaceAppCo c1 c2) = AppCo <$> go c1 <*> go c2
go (IfaceForAllCo tv k c) = do { k' <- go k
; bindIfaceBndr tv $ \ tv' ->
ForAllCo tv' k' <$> go c }
go (IfaceCoVarCo n) = CoVarCo <$> go_var n
go (IfaceAxiomInstCo n i cs) = AxiomInstCo <$> tcIfaceCoAxiom n <*> pure i <*> mapM go cs
go (IfaceUnivCo p r t1 t2) = UnivCo <$> tcIfaceUnivCoProv p <*> pure r
<*> tcIfaceType t1 <*> tcIfaceType t2
go (IfaceSymCo c) = SymCo <$> go c
go (IfaceTransCo c1 c2) = TransCo <$> go c1
<*> go c2
go (IfaceInstCo c1 t2) = InstCo <$> go c1
<*> go t2
go (IfaceNthCo d c) = do { c' <- go c
; return $ mkNthCo (nthCoRole d c') d c' }
go (IfaceLRCo lr c) = LRCo lr <$> go c
go (IfaceKindCo c) = KindCo <$> go c
go (IfaceSubCo c) = SubCo <$> go c
go (IfaceAxiomRuleCo ax cos) = AxiomRuleCo <$> tcIfaceCoAxiomRule ax
<*> mapM go cos
go (IfaceFreeCoVar c) = pprPanic "tcIfaceCo:IfaceFreeCoVar" (ppr c)
go (IfaceHoleCo c) = pprPanic "tcIfaceCo:IfaceHoleCo" (ppr c)
go_var :: FastString -> IfL CoVar
go_var = tcIfaceLclId
tcIfaceUnivCoProv :: IfaceUnivCoProv -> IfL UnivCoProvenance
tcIfaceUnivCoProv (IfacePhantomProv kco) = PhantomProv <$> tcIfaceCo kco
tcIfaceUnivCoProv (IfaceProofIrrelProv kco) = ProofIrrelProv <$> tcIfaceCo kco
tcIfaceUnivCoProv (IfacePluginProv str) = return $ PluginProv str
tcIfaceExpr :: IfaceExpr -> IfL CoreExpr
tcIfaceExpr (IfaceType ty)
= Type <$> tcIfaceType ty
tcIfaceExpr (IfaceCo co)
= Coercion <$> tcIfaceCo co
tcIfaceExpr (IfaceCast expr co)
= Cast <$> tcIfaceExpr expr <*> tcIfaceCo co
tcIfaceExpr (IfaceLcl name)
= Var <$> tcIfaceLclId name
tcIfaceExpr (IfaceExt gbl)
= Var <$> tcIfaceExtId gbl
tcIfaceExpr (IfaceLit lit)
= do lit' <- tcIfaceLit lit
return (Lit lit')
tcIfaceExpr (IfaceFCall cc ty) = do
ty' <- tcIfaceType ty
u <- newUnique
dflags <- getDynFlags
return (Var (mkFCallId dflags u cc ty'))
tcIfaceExpr (IfaceTuple sort args)
= do { args' <- mapM tcIfaceExpr args
; tc <- tcTupleTyCon False sort arity
; let con_tys = map exprType args'
some_con_args = map Type con_tys ++ args'
con_args = case sort of
UnboxedTuple -> map (Type . getRuntimeRep) con_tys ++ some_con_args
_ -> some_con_args
con_id = dataConWorkId (tyConSingleDataCon tc)
; return (mkApps (Var con_id) con_args) }
where
arity = length args
tcIfaceExpr (IfaceLam (bndr, os) body)
= bindIfaceBndr bndr $ \bndr' ->
Lam (tcIfaceOneShot os bndr') <$> tcIfaceExpr body
where
tcIfaceOneShot IfaceOneShot b = setOneShotLambda b
tcIfaceOneShot _ b = b
tcIfaceExpr (IfaceApp fun arg)
= App <$> tcIfaceExpr fun <*> tcIfaceExpr arg
tcIfaceExpr (IfaceECase scrut ty)
= do { scrut' <- tcIfaceExpr scrut
; ty' <- tcIfaceType ty
; return (castBottomExpr scrut' ty') }
tcIfaceExpr (IfaceCase scrut case_bndr alts) = do
scrut' <- tcIfaceExpr scrut
case_bndr_name <- newIfaceName (mkVarOccFS case_bndr)
let
scrut_ty = exprType scrut'
case_mult = Many
case_bndr' = mkLocalIdOrCoVar case_bndr_name case_mult scrut_ty
tc_app = splitTyConApp scrut_ty
extendIfaceIdEnv [case_bndr'] $ do
alts' <- mapM (tcIfaceAlt scrut' case_mult tc_app) alts
return (Case scrut' case_bndr' (coreAltsType alts') alts')
tcIfaceExpr (IfaceLet (IfaceNonRec (IfLetBndr fs ty info ji) rhs) body)
= do { name <- newIfaceName (mkVarOccFS fs)
; ty' <- tcIfaceType ty
; id_info <- tcIdInfo False
NotTopLevel name ty' info
; let id = mkLocalIdWithInfo name Many ty' id_info
`asJoinId_maybe` tcJoinInfo ji
; rhs' <- tcIfaceExpr rhs
; body' <- extendIfaceIdEnv [id] (tcIfaceExpr body)
; return (Let (NonRec id rhs') body') }
tcIfaceExpr (IfaceLet (IfaceRec pairs) body)
= do { ids <- mapM tc_rec_bndr (map fst pairs)
; extendIfaceIdEnv ids $ do
{ pairs' <- zipWithM tc_pair pairs ids
; body' <- tcIfaceExpr body
; return (Let (Rec pairs') body') } }
where
tc_rec_bndr (IfLetBndr fs ty _ ji)
= do { name <- newIfaceName (mkVarOccFS fs)
; ty' <- tcIfaceType ty
; return (mkLocalId name Many ty' `asJoinId_maybe` tcJoinInfo ji) }
tc_pair (IfLetBndr _ _ info _, rhs) id
= do { rhs' <- tcIfaceExpr rhs
; id_info <- tcIdInfo False
NotTopLevel (idName id) (idType id) info
; return (setIdInfo id id_info, rhs') }
tcIfaceExpr (IfaceTick tickish expr) = do
expr' <- tcIfaceExpr expr
dbgLvl <- fmap debugLevel getDynFlags
case tickish of
IfaceSource{} | dbgLvl == 0
-> return expr'
_otherwise -> do
tickish' <- tcIfaceTickish tickish
return (Tick tickish' expr')
tcIfaceTickish :: IfaceTickish -> IfM lcl CoreTickish
tcIfaceTickish (IfaceHpcTick modl ix) = return (HpcTick modl ix)
tcIfaceTickish (IfaceSCC cc tick push) = return (ProfNote cc tick push)
tcIfaceTickish (IfaceSource src name) = return (SourceNote src name)
tcIfaceLit :: Literal -> IfL Literal
tcIfaceLit lit = return lit
tcIfaceAlt :: CoreExpr -> Mult -> (TyCon, [Type])
-> IfaceAlt
-> IfL CoreAlt
tcIfaceAlt _ _ _ (IfaceAlt IfaceDefault names rhs)
= ASSERT( null names ) do
rhs' <- tcIfaceExpr rhs
return (Alt DEFAULT [] rhs')
tcIfaceAlt _ _ _ (IfaceAlt (IfaceLitAlt lit) names rhs)
= ASSERT( null names ) do
lit' <- tcIfaceLit lit
rhs' <- tcIfaceExpr rhs
return (Alt (LitAlt lit') [] rhs')
tcIfaceAlt scrut mult (tycon, inst_tys) (IfaceAlt (IfaceDataAlt data_occ) arg_strs rhs)
= do { con <- tcIfaceDataCon data_occ
; when (debugIsOn && not (con `elem` tyConDataCons tycon))
(failIfM (ppr scrut $$ ppr con $$ ppr tycon $$ ppr (tyConDataCons tycon)))
; tcIfaceDataAlt mult con inst_tys arg_strs rhs }
tcIfaceDataAlt :: Mult -> DataCon -> [Type] -> [FastString] -> IfaceExpr
-> IfL CoreAlt
tcIfaceDataAlt mult con inst_tys arg_strs rhs
= do { us <- newUniqueSupply
; let uniqs = uniqsFromSupply us
; let (ex_tvs, arg_ids)
= dataConRepFSInstPat arg_strs uniqs mult con inst_tys
; rhs' <- extendIfaceEnvs ex_tvs $
extendIfaceIdEnv arg_ids $
tcIfaceExpr rhs
; return (Alt (DataAlt con) (ex_tvs ++ arg_ids) rhs') }
tcIdDetails :: Type -> IfaceIdDetails -> IfL IdDetails
tcIdDetails _ IfVanillaId = return VanillaId
tcIdDetails ty IfDFunId
= return (DFunId (isNewTyCon (classTyCon cls)))
where
(_, _, cls, _) = tcSplitDFunTy ty
tcIdDetails _ (IfRecSelId tc naughty)
= do { tc' <- either (fmap RecSelData . tcIfaceTyCon)
(fmap (RecSelPatSyn . tyThingPatSyn) . tcIfaceDecl False)
tc
; return (RecSelId { sel_tycon = tc', sel_naughty = naughty }) }
where
tyThingPatSyn (AConLike (PatSynCon ps)) = ps
tyThingPatSyn _ = panic "tcIdDetails: expecting patsyn"
tcIdInfo :: Bool -> TopLevelFlag -> Name -> Type -> IfaceIdInfo -> IfL IdInfo
tcIdInfo ignore_prags toplvl name ty info = do
lcl_env <- getLclEnv
let init_info = if if_boot lcl_env == IsBoot
then vanillaIdInfo `setUnfoldingInfo` BootUnfolding
else vanillaIdInfo
foldlM tcPrag init_info (needed_prags info)
where
needed_prags :: [IfaceInfoItem] -> [IfaceInfoItem]
needed_prags items
| not ignore_prags = items
| otherwise = filter need_prag items
need_prag :: IfaceInfoItem -> Bool
need_prag (HsUnfold _ (IfCompulsory {})) = True
need_prag _ = False
tcPrag :: IdInfo -> IfaceInfoItem -> IfL IdInfo
tcPrag info HsNoCafRefs = return (info `setCafInfo` NoCafRefs)
tcPrag info (HsArity arity) = return (info `setArityInfo` arity)
tcPrag info (HsStrictness str) = return (info `setStrictnessInfo` str)
tcPrag info (HsCpr cpr) = return (info `setCprInfo` cpr)
tcPrag info (HsInline prag) = return (info `setInlinePragInfo` prag)
tcPrag info HsLevity = return (info `setNeverLevPoly` ty)
tcPrag info (HsLFInfo lf_info) = do
lf_info <- tcLFInfo lf_info
return (info `setLFInfo` lf_info)
tcPrag info (HsUnfold lb if_unf)
= do { unf <- tcUnfolding toplvl name ty info if_unf
; let info1 | lb = info `setOccInfo` strongLoopBreaker
| otherwise = info
; return (info1 `setUnfoldingInfo` unf) }
tcJoinInfo :: IfaceJoinInfo -> Maybe JoinArity
tcJoinInfo (IfaceJoinPoint ar) = Just ar
tcJoinInfo IfaceNotJoinPoint = Nothing
tcLFInfo :: IfaceLFInfo -> IfL LambdaFormInfo
tcLFInfo lfi = case lfi of
IfLFReEntrant rep_arity ->
return (LFReEntrant TopLevel rep_arity True ArgUnknown)
IfLFThunk updatable mb_fun ->
return (LFThunk TopLevel True updatable NonStandardThunk mb_fun)
IfLFUnlifted ->
return LFUnlifted
IfLFCon con_name ->
LFCon <$!> tcIfaceDataCon con_name
IfLFUnknown fun_flag ->
return (LFUnknown fun_flag)
tcUnfolding :: TopLevelFlag -> Name -> Type -> IdInfo -> IfaceUnfolding -> IfL Unfolding
tcUnfolding toplvl name _ info (IfCoreUnfold stable if_expr)
= do { uf_opts <- unfoldingOpts <$> getDynFlags
; mb_expr <- tcPragExpr False toplvl name if_expr
; let unf_src | stable = InlineStable
| otherwise = InlineRhs
; return $ case mb_expr of
Nothing -> NoUnfolding
Just expr -> mkFinalUnfolding uf_opts unf_src strict_sig expr
}
where
strict_sig = strictnessInfo info
tcUnfolding toplvl name _ _ (IfCompulsory if_expr)
= do { mb_expr <- tcPragExpr True toplvl name if_expr
; return (case mb_expr of
Nothing -> NoUnfolding
Just expr -> mkCompulsoryUnfolding' expr) }
tcUnfolding toplvl name _ _ (IfInlineRule arity unsat_ok boring_ok if_expr)
= do { mb_expr <- tcPragExpr False toplvl name if_expr
; return (case mb_expr of
Nothing -> NoUnfolding
Just expr -> mkCoreUnfolding InlineStable True expr guidance )}
where
guidance = UnfWhen { ug_arity = arity, ug_unsat_ok = unsat_ok, ug_boring_ok = boring_ok }
tcUnfolding _toplvl name dfun_ty _ (IfDFunUnfold bs ops)
= bindIfaceBndrs bs $ \ bs' ->
do { mb_ops1 <- forkM_maybe doc $ mapM tcIfaceExpr ops
; return (case mb_ops1 of
Nothing -> noUnfolding
Just ops1 -> mkDFunUnfolding bs' (classDataCon cls) ops1) }
where
doc = text "Class ops for dfun" <+> ppr name
(_, _, cls, _) = tcSplitDFunTy dfun_ty
tcPragExpr :: Bool
-> TopLevelFlag -> Name -> IfaceExpr -> IfL (Maybe CoreExpr)
tcPragExpr is_compulsory toplvl name expr
= forkM_maybe doc $ do
core_expr' <- tcIfaceExpr expr
when (isTopLevel toplvl) $
whenGOptM Opt_DoCoreLinting $ do
in_scope <- get_in_scope
dflags <- getDynFlags
logger <- getLogger
case lintUnfolding is_compulsory dflags noSrcLoc in_scope core_expr' of
Nothing -> return ()
Just errs -> liftIO $
displayLintResults logger dflags False doc
(pprCoreExpr core_expr') (emptyBag, errs)
return core_expr'
where
doc = ppWhen is_compulsory (text "Compulsory") <+>
text "Unfolding of" <+> ppr name
get_in_scope :: IfL VarSet
get_in_scope
= do { (gbl_env, lcl_env) <- getEnvs
; rec_ids <- case if_rec_types gbl_env of
Nothing -> return []
Just (_, get_env) -> do
{ type_env <- setLclEnv () get_env
; return (typeEnvIds type_env) }
; return (bindingsVars (if_tv_env lcl_env) `unionVarSet`
bindingsVars (if_id_env lcl_env) `unionVarSet`
mkVarSet rec_ids) }
bindingsVars :: FastStringEnv Var -> VarSet
bindingsVars ufm = mkVarSet $ nonDetEltsUFM ufm
tcIfaceOneShot :: IfaceOneShot -> OneShotInfo
tcIfaceOneShot IfaceNoOneShot = NoOneShotInfo
tcIfaceOneShot IfaceOneShot = OneShotLam
tcIfaceGlobal :: Name -> IfL TyThing
tcIfaceGlobal name
| Just thing <- wiredInNameTyThing_maybe name
= do { ifCheckWiredInThing thing; return thing }
| otherwise
= do { env <- getGblEnv
; case if_rec_types env of {
Just (mod, get_type_env)
| nameIsLocalOrFrom mod name
-> do
{ type_env <- setLclEnv () get_type_env
; case lookupNameEnv type_env name of
Just thing -> return thing
Nothing -> via_external
}
; _ -> via_external }}
where
via_external = do
{ hsc_env <- getTopEnv
; mb_thing <- liftIO (lookupType hsc_env name)
; case mb_thing of {
Just thing -> return thing ;
Nothing -> do
{ mb_thing <- importDecl name
; case mb_thing of
Failed err -> failIfM err
Succeeded thing -> return thing
}}}
tcIfaceTyCon :: IfaceTyCon -> IfL TyCon
tcIfaceTyCon (IfaceTyCon name info)
= do { thing <- tcIfaceGlobal name
; return $ case ifaceTyConIsPromoted info of
NotPromoted -> tyThingTyCon thing
IsPromoted -> promoteDataCon $ tyThingDataCon thing }
tcIfaceCoAxiom :: Name -> IfL (CoAxiom Branched)
tcIfaceCoAxiom name = do { thing <- tcIfaceImplicit name
; return (tyThingCoAxiom thing) }
tcIfaceCoAxiomRule :: IfLclName -> IfL CoAxiomRule
tcIfaceCoAxiomRule n
= case lookupUFM typeNatCoAxiomRules n of
Just ax -> return ax
_ -> pprPanic "tcIfaceCoAxiomRule" (ppr n)
tcIfaceDataCon :: Name -> IfL DataCon
tcIfaceDataCon name = do { thing <- tcIfaceGlobal name
; case thing of
AConLike (RealDataCon dc) -> return dc
_ -> pprPanic "tcIfaceDataCon" (ppr name$$ ppr thing) }
tcIfaceConLike :: Name -> IfL ConLike
tcIfaceConLike name = do { thing <- tcIfaceGlobal name
; case thing of
AConLike cl -> return cl
_ -> pprPanic "tcIfaceConLike" (ppr name$$ ppr thing) }
tcIfaceExtId :: Name -> IfL Id
tcIfaceExtId name = do { thing <- tcIfaceGlobal name
; case thing of
AnId id -> return id
_ -> pprPanic "tcIfaceExtId" (ppr name$$ ppr thing) }
tcIfaceImplicit :: Name -> IfL TyThing
tcIfaceImplicit n = do
lcl_env <- getLclEnv
case if_implicits_env lcl_env of
Nothing -> tcIfaceGlobal n
Just tenv ->
case lookupTypeEnv tenv n of
Nothing -> pprPanic "tcIfaceInst" (ppr n $$ ppr tenv)
Just tything -> return tything
bindIfaceId :: IfaceIdBndr -> (Id -> IfL a) -> IfL a
bindIfaceId (w, fs, ty) thing_inside
= do { name <- newIfaceName (mkVarOccFS fs)
; ty' <- tcIfaceType ty
; w' <- tcIfaceType w
; let id = mkLocalIdOrCoVar name w' ty'
; extendIfaceIdEnv [id] (thing_inside id) }
bindIfaceIds :: [IfaceIdBndr] -> ([Id] -> IfL a) -> IfL a
bindIfaceIds [] thing_inside = thing_inside []
bindIfaceIds (b:bs) thing_inside
= bindIfaceId b $ \b' ->
bindIfaceIds bs $ \bs' ->
thing_inside (b':bs')
bindIfaceBndr :: IfaceBndr -> (CoreBndr -> IfL a) -> IfL a
bindIfaceBndr (IfaceIdBndr bndr) thing_inside
= bindIfaceId bndr thing_inside
bindIfaceBndr (IfaceTvBndr bndr) thing_inside
= bindIfaceTyVar bndr thing_inside
bindIfaceBndrs :: [IfaceBndr] -> ([CoreBndr] -> IfL a) -> IfL a
bindIfaceBndrs [] thing_inside = thing_inside []
bindIfaceBndrs (b:bs) thing_inside
= bindIfaceBndr b $ \ b' ->
bindIfaceBndrs bs $ \ bs' ->
thing_inside (b':bs')
bindIfaceForAllBndrs :: [VarBndr IfaceBndr vis] -> ([VarBndr TyCoVar vis] -> IfL a) -> IfL a
bindIfaceForAllBndrs [] thing_inside = thing_inside []
bindIfaceForAllBndrs (bndr:bndrs) thing_inside
= bindIfaceForAllBndr bndr $ \tv vis ->
bindIfaceForAllBndrs bndrs $ \bndrs' ->
thing_inside (Bndr tv vis : bndrs')
bindIfaceForAllBndr :: (VarBndr IfaceBndr vis) -> (TyCoVar -> vis -> IfL a) -> IfL a
bindIfaceForAllBndr (Bndr (IfaceTvBndr tv) vis) thing_inside
= bindIfaceTyVar tv $ \tv' -> thing_inside tv' vis
bindIfaceForAllBndr (Bndr (IfaceIdBndr tv) vis) thing_inside
= bindIfaceId tv $ \tv' -> thing_inside tv' vis
bindIfaceTyVar :: IfaceTvBndr -> (TyVar -> IfL a) -> IfL a
bindIfaceTyVar (occ,kind) thing_inside
= do { name <- newIfaceName (mkTyVarOccFS occ)
; tyvar <- mk_iface_tyvar name kind
; extendIfaceTyVarEnv [tyvar] (thing_inside tyvar) }
bindIfaceTyVars :: [IfaceTvBndr] -> ([TyVar] -> IfL a) -> IfL a
bindIfaceTyVars [] thing_inside = thing_inside []
bindIfaceTyVars (bndr:bndrs) thing_inside
= bindIfaceTyVar bndr $ \tv ->
bindIfaceTyVars bndrs $ \tvs ->
thing_inside (tv : tvs)
mk_iface_tyvar :: Name -> IfaceKind -> IfL TyVar
mk_iface_tyvar name ifKind
= do { kind <- tcIfaceType ifKind
; return (Var.mkTyVar name kind) }
bindIfaceTyConBinders :: [IfaceTyConBinder]
-> ([TyConBinder] -> IfL a) -> IfL a
bindIfaceTyConBinders [] thing_inside = thing_inside []
bindIfaceTyConBinders (b:bs) thing_inside
= bindIfaceTyConBinderX bindIfaceBndr b $ \ b' ->
bindIfaceTyConBinders bs $ \ bs' ->
thing_inside (b':bs')
bindIfaceTyConBinders_AT :: [IfaceTyConBinder]
-> ([TyConBinder] -> IfL a) -> IfL a
bindIfaceTyConBinders_AT [] thing_inside
= thing_inside []
bindIfaceTyConBinders_AT (b : bs) thing_inside
= bindIfaceTyConBinderX bind_tv b $ \b' ->
bindIfaceTyConBinders_AT bs $ \bs' ->
thing_inside (b':bs')
where
bind_tv tv thing
= do { mb_tv <- lookupIfaceVar tv
; case mb_tv of
Just b' -> thing b'
Nothing -> bindIfaceBndr tv thing }
bindIfaceTyConBinderX :: (IfaceBndr -> (TyCoVar -> IfL a) -> IfL a)
-> IfaceTyConBinder
-> (TyConBinder -> IfL a) -> IfL a
bindIfaceTyConBinderX bind_tv (Bndr tv vis) thing_inside
= bind_tv tv $ \tv' ->
thing_inside (Bndr tv' vis)