- primitive operations
\begin{code}
-{-# OPTIONS -fno-warn-missing-signatures #-}
--- The above warning supression flag is a temporary kludge.
--- While working on this module you are encouraged to remove it and fix
--- any warnings in the module. See
--- <http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings>
--- for details
-
module MkId (
mkDictFunId, mkDefaultMethodId,
mkDictSelId,
-- by the caller. So doing CPR for them may in fact make
-- things worse.
+mkLocals :: Int -> [Type] -> ([Id], Int)
mkLocals i tys = (zipWith mkTemplateLocal [i..i+n-1] tys, i+n)
where
n = length tys
mkBreakPointOpId uniq mod ix = mkTickBox' uniq mod ix ty
where ty = mkSigmaTy [openAlphaTyVar] [] openAlphaTy
+mkTickBox' :: Unique -> Module -> TickBoxId -> Type -> Id
mkTickBox' uniq mod ix ty = mkGlobalId (TickBoxOpId tickbox) name ty info
where
tickbox = TickBox mod ix
that they aren't discarded by the occurrence analyser.
\begin{code}
-mkDefaultMethodId dm_name ty = mkExportedLocalId dm_name ty
+mkDefaultMethodId :: Id -- Selector Id
+ -> Name -- Default method name
+ -> Id -- Default method Id
+mkDefaultMethodId sel_id dm_name = mkExportedLocalId dm_name (idType sel_id)
mkDictFunId :: Name -- Name to use for the dict fun;
-> [TyVar]
another gun with which to shoot yourself in the foot.
\begin{code}
+mkWiredInIdName :: Module -> FastString -> Unique -> Id -> Name
mkWiredInIdName mod fs uniq id
= mkWiredInName mod (mkOccNameFS varName fs) uniq (AnId id) UserSyntax
+unsafeCoerceName, nullAddrName, seqName, realWorldName :: Name
+lazyIdName, errorName, recSelErrorName, runtimeErrorName :: Name
+irrefutPatErrorName, recConErrorName, patErrorName :: Name
+nonExhaustiveGuardsErrorName, noMethodBindingErrorName :: Name
unsafeCoerceName = mkWiredInIdName gHC_PRIM (fsLit "unsafeCoerce#") unsafeCoerceIdKey unsafeCoerceId
nullAddrName = mkWiredInIdName gHC_PRIM (fsLit "nullAddr#") nullAddrIdKey nullAddrId
seqName = mkWiredInIdName gHC_PRIM (fsLit "seq") seqIdKey seqId
\begin{code}
------------------------------------------------
-- unsafeCoerce# :: forall a b. a -> b
+unsafeCoerceId :: Id
unsafeCoerceId
= pcMiscPrelId unsafeCoerceName ty info
where
This comes up in strictness analysis
\begin{code}
+realWorldPrimId :: Id
realWorldPrimId -- :: State# RealWorld
= pcMiscPrelId realWorldName realWorldStatePrimTy
(noCafIdInfo `setUnfoldingInfo` evaldUnfolding)
mkImpossibleExpr res_ty
= mkRuntimeErrorApp rUNTIME_ERROR_ID res_ty "Impossible case alternative"
+rEC_SEL_ERROR_ID, rUNTIME_ERROR_ID, iRREFUT_PAT_ERROR_ID, rEC_CON_ERROR_ID :: Id
+pAT_ERROR_ID, nO_METHOD_BINDING_ERROR_ID, nON_EXHAUSTIVE_GUARDS_ERROR_ID :: Id
rEC_SEL_ERROR_ID = mkRuntimeErrorId recSelErrorName
rUNTIME_ERROR_ID = mkRuntimeErrorId runtimeErrorName
iRREFUT_PAT_ERROR_ID = mkRuntimeErrorId irrefutPatErrorName
\end{code}
\begin{code}
+eRROR_ID :: Id
eRROR_ID = pc_bottoming_Id errorName errorTy
errorTy :: Type
\begin{code}
tcClassDecl2 :: LTyClDecl Name -- The class declaration
- -> TcM ([Id], LHsBinds Id)
+ -> TcM (LHsBinds Id)
tcClassDecl2 (L loc (ClassDecl {tcdLName = class_name, tcdSigs = sigs,
tcdMeths = default_binds}))
- = recoverM (return ([], emptyLHsBinds)) $
- setSrcSpan loc $
+ = recoverM (return emptyLHsBinds) $
+ setSrcSpan loc $
do { clas <- tcLookupLocatedClass class_name
-- We make a separate binding for each default method.
this_dict default_binds
sig_fn prag_fn
- ; dm_stuff <- tcExtendTyVarEnv clas_tyvars $
+ ; dm_binds <- tcExtendTyVarEnv clas_tyvars $
mapM tc_dm op_items
- ; let (dm_ids, defm_binds) = unzip (catMaybes dm_stuff)
- ; return (dm_ids, listToBag defm_binds) }
+ ; return (listToBag (catMaybes dm_binds)) }
tcClassDecl2 d = pprPanic "tcClassDecl2" (ppr d)
tcDefMeth :: Class -> [TyVar] -> Inst -> LHsBinds Name
-> TcSigFun -> TcPragFun -> ClassOpItem
- -> TcM (Maybe (Id, LHsBind Id))
+ -> TcM (Maybe (LHsBind Id))
-- Generate code for polymorphic default methods only (hence DefMeth)
-- (Generic default methods have turned into instance decls by now.)
-- This is incompatible with Hugs, which expects a polymorphic
`orElse` pprPanic "tcDefMeth" (ppr sel_id)
-- dm_info = DefMeth dm_name only if there is a binding in binds_in
- dm_sig_fn _ = sig_fn sel_name
- dm_ty = idType sel_id
- dm_id = mkDefaultMethodId dm_name dm_ty
+ dm_sig_fn _ = sig_fn sel_name
+ dm_id = mkDefaultMethodId sel_id dm_name
local_dm_type = instantiateMethod clas sel_id (mkTyVarTys tyvars)
local_dm_id = mkLocalId local_dm_name local_dm_type
tcInstanceMethodBody :: InstLoc -> [TcTyVar] -> [Inst]
-> ([Inst], LHsBinds Id) -> Id -> Id
-> TcSigFun -> TcSpecPrags -> LHsBind Name
- -> TcM (Id, LHsBind Id)
+ -> TcM (LHsBind Id)
tcInstanceMethodBody inst_loc tyvars dfun_dicts
(this_dict, this_bind) meth_id local_meth_id
meth_sig_fn spec_prags bind@(L loc _)
dfun_lam_vars = map instToVar dfun_dicts -- Includes equalities
- ; return (meth_id, L loc full_bind) }
+ ; return (L loc full_bind) }
where
no_prag_fn _ = [] -- No pragmas for local_meth_id;
-- they are all for meth_id
; at_idx_tycons = concat at_tycons_s ++ idx_tycons
; clas_decls = filter (isClassDecl.unLoc) tycl_decls
; implicit_things = concatMap implicitTyThings at_idx_tycons
- ; aux_binds = mkAuxBinds at_idx_tycons
+ ; aux_binds = mkRecSelBinds at_idx_tycons
}
-- (2) Add the tycons of indexed types and their implicit
\begin{code}
tcInstDecls2 :: [LTyClDecl Name] -> [InstInfo Name]
- -> TcM (LHsBinds Id, TcLclEnv)
+ -> TcM (LHsBinds Id)
-- (a) From each class declaration,
-- generate any default-method bindings
-- (b) From each instance decl
tcInstDecls2 tycl_decls inst_decls
= do { -- (a) Default methods from class decls
let class_decls = filter (isClassDecl . unLoc) tycl_decls
- ; (dm_ids_s, dm_binds_s) <- mapAndUnzipM tcClassDecl2 class_decls
+ ; dm_binds_s <- mapM tcClassDecl2 class_decls
- ; tcExtendIdEnv (concat dm_ids_s) $ do
-
-- (b) instance declarations
- { inst_binds_s <- mapM tcInstDecl2 inst_decls
+ ; inst_binds_s <- mapM tcInstDecl2 inst_decls
-- Done
- ; let binds = unionManyBags dm_binds_s `unionBags`
- unionManyBags inst_binds_s
- ; tcl_env <- getLclEnv -- Default method Ids in here
- ; return (binds, tcl_env) } }
+ ; return (unionManyBags dm_binds_s `unionBags`
+ unionManyBags inst_binds_s) }
tcInstDecl2 :: InstInfo Name -> TcM (LHsBinds Id)
tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = ibinds })
= add_meth_ctxt rn_bind $
do { (meth_id1, spec_prags) <- tcPrags NonRecursive False True
meth_id (prag_fn sel_name)
- ; tcInstanceMethodBody (instLoc this_dict)
+ ; bind <- tcInstanceMethodBody (instLoc this_dict)
tyvars dfun_dicts
([this_dict], this_dict_bind)
meth_id1 local_meth_id
meth_sig_fn
(SpecPrags (spec_inst_prags ++ spec_prags))
- rn_bind }
+ rn_bind
+ ; return (meth_id1, bind) }
--------------
tc_default :: DefMeth -> TcM (Id, LHsBind Id)
-- any mutually recursive types are done right
-- Just discard the auxiliary bindings; they are generated
-- only for Haskell source code, and should already be in Core
- (tcg_env, _aux_binds) <- tcTyAndClassDecls emptyModDetails rn_decls ;
+ (tcg_env, _aux_binds, _dm_ids) <- tcTyAndClassDecls emptyModDetails rn_decls ;
setGblEnv tcg_env $ do {
-- Make the new type env available to stuff slurped from interface files
-- Typecheck type/class decls
; traceTc (text "Tc2")
- ; (tcg_env, aux_binds) <- tcTyAndClassDecls emptyModDetails tycl_decls
- ; setGblEnv tcg_env $ do {
+ ; (tcg_env, aux_binds, dm_ids)
+ <- tcTyAndClassDecls emptyModDetails tycl_decls
+ ; setGblEnv tcg_env $
+ tcExtendIdEnv dm_ids $ do {
-- Typecheck instance decls
-- Family instance declarations are rejected here
-- The latter come in via tycl_decls
traceTc (text "Tc2") ;
- (tcg_env, aux_binds) <- tcTyAndClassDecls boot_details tycl_decls ;
+ (tcg_env, aux_binds, dm_ids) <- tcTyAndClassDecls boot_details tycl_decls ;
-- If there are any errors, tcTyAndClassDecls fails here
- setGblEnv tcg_env $ do {
+ setGblEnv tcg_env $
+ tcExtendIdEnv dm_ids $ do {
+
-- Source-language instances, including derivings,
-- and import the supporting declarations
traceTc (text "Tc3") ;
(tc_val_binds, tcl_env) <- setLclTypeEnv tcl_env $
tcTopBinds val_binds;
+ setLclTypeEnv tcl_env $ do { -- Environment doesn't change now
+
-- Second pass over class and instance declarations,
traceTc (text "Tc6") ;
- (inst_binds, tcl_env) <- setLclTypeEnv tcl_env $
- tcInstDecls2 tycl_decls inst_infos ;
- showLIE (text "after instDecls2") ;
-
- setLclTypeEnv tcl_env $ do { -- Environment doesn't change now
+ inst_binds <- tcInstDecls2 tycl_decls inst_infos ;
+ showLIE (text "after instDecls2") ;
-- Foreign exports
traceTc (text "Tc7") ;
\begin{code}
module TcTyClsDecls (
- tcTyAndClassDecls, tcFamInstDecl, mkAuxBinds
+ tcTyAndClassDecls, tcFamInstDecl, mkRecSelBinds
) where
#include "HsVersions.h"
import TyCon
import DataCon
import Id
-import MkId ( rEC_SEL_ERROR_ID )
+import MkId ( rEC_SEL_ERROR_ID, mkDefaultMethodId )
import IdInfo
import Var
import VarSet
tcTyAndClassDecls :: ModDetails -> [LTyClDecl Name]
-> TcM (TcGblEnv, -- Input env extended by types and classes
-- and their implicit Ids,DataCons
- HsValBinds Name) -- Renamed bindings for record selectors
+ HsValBinds Name, -- Renamed bindings for record selectors
+ [Id]) -- Default method ids
+
-- Fails if there are any errors
tcTyAndClassDecls boot_details allDecls
-- second time here. This doesn't matter as the definitions are
-- the same.
; let { implicit_things = concatMap implicitTyThings alg_tyclss
- ; aux_binds = mkAuxBinds alg_tyclss }
+ ; rec_sel_binds = mkRecSelBinds alg_tyclss
+ ; dm_ids = mkDefaultMethodIds alg_tyclss }
; traceTc ((text "Adding" <+> ppr alg_tyclss)
$$ (text "and" <+> ppr implicit_things))
; env <- tcExtendGlobalEnv implicit_things getGblEnv
- ; return (env, aux_binds) }
+ ; return (env, rec_sel_binds, dm_ids) }
}
where
-- Pull associated types out of class declarations, to tie them into the
%************************************************************************
\begin{code}
-mkAuxBinds :: [TyThing] -> HsValBinds Name
+mkDefaultMethodIds :: [TyThing] -> [Id]
+-- See Note [Default method Ids and Template Haskell]
+mkDefaultMethodIds things
+ = [ mkDefaultMethodId sel_id dm_name
+ | AClass cls <- things
+ , (sel_id, DefMeth dm_name) <- classOpItems cls ]
+\end{code}
+
+Note [Default method Ids and Template Haskell]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider this (Trac #4169):
+ class Numeric a where
+ fromIntegerNum :: a
+ fromIntegerNum = ...
+
+ ast :: Q [Dec]
+ ast = [d| instance Numeric Int |]
+
+When we typecheck 'ast' we have done the first pass over the class decl
+(in tcTyClDecls), but we have not yet typechecked the default-method
+declarations (becuase they can mention value declarations). So we
+must bring the default method Ids into scope first (so they can be seen
+when typechecking the [d| .. |] quote, and typecheck them later.
+
+\begin{code}
+mkRecSelBinds :: [TyThing] -> HsValBinds Name
-- NB We produce *un-typechecked* bindings, rather like 'deriving'
-- This makes life easier, because the later type checking will add
-- all necessary type abstractions and applications
-mkAuxBinds ty_things
+mkRecSelBinds ty_things
= ValBindsOut [(NonRecursive, b) | b <- binds] sigs
where
(sigs, binds) = unzip rec_sels
mkClass, classTyVars, classArity,
classKey, className, classATs, classSelIds, classTyCon, classMethods,
- classBigSig, classExtraBigSig, classTvsFds, classSCTheta
+ classOpItems,classBigSig, classExtraBigSig, classTvsFds, classSCTheta
) where
#include "Typeable.h"
classMethods (Class {classOpStuff = op_stuff})
= [op_sel | (op_sel, _) <- op_stuff]
+classOpItems :: Class -> [ClassOpItem]
+classOpItems (Class {classOpStuff = op_stuff}) = op_stuff
+
classTvsFds :: Class -> ([TyVar], [FunDep TyVar])
classTvsFds c
= (classTyVars c, classFunDeps c)