Commit 9ffadf21 authored by simonpj@microsoft.com's avatar simonpj@microsoft.com

Make record selectors into ordinary functions

This biggish patch addresses Trac #2670.  The main effect is to make
record selectors into ordinary functions, whose unfoldings appear in
interface files, in contrast to their previous existence as magic
"implicit Ids".  This means that the usual machinery of optimisation,
analysis, and inlining applies to them, which was failing before when
the selector was somewhat complicated.  (Which it can be when
strictness annotations, unboxing annotations, and GADTs are involved.)

The change involves the following points

* Changes in Var.lhs to the representation of Var.  Now a LocalId can
  have an IdDetails as well as a GlobalId.  In particular, the
  information that an Id is a record selector is kept in the
  IdDetails.  While compiling the current module, the record selector
  *must* be a LocalId, so that it participates properly in compilation
  (free variables etc).

  This led me to change the (hidden) representation of Var, so that there
  is now only one constructor for Id, not two.

* The IdDetails is persisted into interface files, so that an
  importing module can see which Ids are records selectors.

* In TcTyClDecls, we generate the record-selector bindings in renamed,
  but not typechecked form.  In this way, we can get the typechecker
  to add all the types and so on, which is jolly helpful especially
  when GADTs or type families are involved.  Just like derived
  instance declarations.

  This is the big new chunk of 180 lines of code (much of which is
  commentary).  A call to the same function, mkAuxBinds, is needed in
  TcInstDcls for associated types.

* The typechecker therefore has to pin the correct IdDetails on to 
  the record selector, when it typechecks it.  There was a neat way
  to do this, by adding a new sort of signature to HsBinds.Sig, namely
  IdSig.  This contains an Id (with the correct Name, Type, and IdDetails);
  the type checker uses it as the binder for the final binding.  This
  worked out rather easily.

* Record selectors are no longer "implicit ids", which entails changes to
     IfaceSyn.ifaceDeclSubBndrs
     HscTypes.implicitTyThings
     TidyPgm.getImplicitBinds
  (These three functions must agree.)

* MkId.mkRecordSelectorId is deleted entirely, some 300+ lines (incl
  comments) of very error prone code.  Happy days.

* A TyCon no longer contains the list of record selectors: 
  algTcSelIds is gone

The renamer is unaffected, including the way that import and export of
record selectors is handled.

Other small things

* IfaceSyn.ifaceDeclSubBndrs had a fragile test for whether a data
  constructor had a wrapper.  I've replaced that with an explicit flag
  in the interface file. More robust I hope.

* I renamed isIdVar to isId, which touched a few otherwise-unrelated files.
parent 24a5fdb5
......@@ -318,7 +318,6 @@ data DataCon
dcOrigArgTys :: [Type], -- Original argument types
-- (before unboxing and flattening of strict fields)
dcOrigResTy :: Type, -- Original result type, as seen by the user
-- INVARIANT: mentions only dcUnivTyVars
-- NB: for a data instance, the original user result type may
-- differ from the DataCon's representation TyCon. Example
-- data instance T [a] where MkT :: a -> T [a]
......@@ -636,8 +635,10 @@ dataConFieldLabels = dcFields
-- | Extract the type for any given labelled field of the 'DataCon'
dataConFieldType :: DataCon -> FieldLabel -> Type
dataConFieldType con label = expectJust "unexpected label" $
lookup label (dcFields con `zip` dcOrigArgTys con)
dataConFieldType con label
= case lookup label (dcFields con `zip` dcOrigArgTys con) of
Just ty -> ty
Nothing -> pprPanic "dataConFieldType" (ppr con <+> ppr label)
-- | The strictness markings decided on by the compiler. Does not include those for
-- existential dictionaries. The list is in one-to-one correspondence with the arity of the 'DataCon'
......@@ -726,7 +727,7 @@ dataConUserType :: DataCon -> Type
--
-- rather than:
--
-- > T :: forall a c. forall b. (c=[a]) => a -> b -> T c
-- > T :: forall a c. forall b. (c~[a]) => a -> b -> T c
--
-- NB: If the constructor is part of a data instance, the result type
-- mentions the family tycon, not the internal one.
......
......@@ -27,14 +27,14 @@ module Id (
-- ** Simple construction
mkGlobalId, mkVanillaGlobal, mkVanillaGlobalWithInfo,
mkLocalId, mkLocalIdWithInfo,
mkLocalId, mkLocalIdWithInfo, mkExportedLocalId,
mkSysLocal, mkSysLocalM, mkUserLocal, mkUserLocalM,
mkTemplateLocals, mkTemplateLocalsNum, mkTemplateLocal,
mkWorkerId, mkExportedLocalId,
mkWorkerId,
-- ** Taking an Id apart
idName, idType, idUnique, idInfo,
isId, globalIdDetails, idPrimRep,
idName, idType, idUnique, idInfo, idDetails,
isId, idPrimRep,
recordSelectorFieldLabel,
-- ** Modifying an Id
......@@ -104,8 +104,13 @@ import CoreSyn ( CoreRule, Unfolding )
import IdInfo
import BasicTypes
-- Imported and re-exported
import Var( Id, DictId,
idInfo, idDetails, globaliseId,
isId, isLocalId, isGlobalId, isExportedId )
import qualified Var
import Var
import TyCon
import Type
import TcType
......@@ -156,26 +161,19 @@ idName :: Id -> Name
idName = Var.varName
idUnique :: Id -> Unique
idUnique = varUnique
idUnique = Var.varUnique
idType :: Id -> Kind
idType = varType
idInfo :: Id -> IdInfo
idInfo = varIdInfo
idType = Var.varType
idPrimRep :: Id -> PrimRep
idPrimRep id = typePrimRep (idType id)
globalIdDetails :: Id -> GlobalIdDetails
globalIdDetails = globalIdVarDetails
setIdName :: Id -> Name -> Id
setIdName = setVarName
setIdName = Var.setVarName
setIdUnique :: Id -> Unique -> Id
setIdUnique = setVarUnique
setIdUnique = Var.setVarUnique
-- | Not only does this set the 'Id' 'Type', it also evaluates the type to try and
-- reduce space usage
......@@ -183,10 +181,10 @@ setIdType :: Id -> Type -> Id
setIdType id ty = seqType ty `seq` Var.setVarType id ty
setIdExported :: Id -> Id
setIdExported = setIdVarExported
setIdExported = Var.setIdExported
setIdNotExported :: Id -> Id
setIdNotExported = setIdVarNotExported
setIdNotExported = Var.setIdNotExported
localiseId :: Id -> Id
-- Make an with the same unique and type as the
......@@ -199,11 +197,8 @@ localiseId id
where
name = idName id
globaliseId :: GlobalIdDetails -> Id -> Id
globaliseId = globaliseIdVar
lazySetIdInfo :: Id -> IdInfo -> Id
lazySetIdInfo = lazySetVarIdInfo
lazySetIdInfo = Var.lazySetIdInfo
setIdInfo :: Id -> IdInfo -> Id
setIdInfo id info = seqIdInfo info `seq` (lazySetIdInfo id info)
......@@ -240,8 +235,8 @@ Anyway, we removed it in March 2008.
\begin{code}
-- | For an explanation of global vs. local 'Id's, see "Var#globalvslocal"
mkGlobalId :: GlobalIdDetails -> Name -> Type -> IdInfo -> Id
mkGlobalId = mkGlobalIdVar
mkGlobalId :: IdDetails -> Name -> Type -> IdInfo -> Id
mkGlobalId = Var.mkGlobalVar
-- | Make a global 'Id' without any extra information at all
mkVanillaGlobal :: Name -> Type -> Id
......@@ -249,7 +244,7 @@ mkVanillaGlobal name ty = mkVanillaGlobalWithInfo name ty vanillaIdInfo
-- | Make a global 'Id' with no global information but some generic 'IdInfo'
mkVanillaGlobalWithInfo :: Name -> Type -> IdInfo -> Id
mkVanillaGlobalWithInfo = mkGlobalId VanillaGlobal
mkVanillaGlobalWithInfo = mkGlobalId VanillaId
-- | For an explanation of global vs. local 'Id's, see "Var#globalvslocal"
......@@ -257,16 +252,18 @@ mkLocalId :: Name -> Type -> Id
mkLocalId name ty = mkLocalIdWithInfo name ty vanillaIdInfo
mkLocalIdWithInfo :: Name -> Type -> IdInfo -> Id
mkLocalIdWithInfo = mkLocalIdVar
mkLocalIdWithInfo name ty info = Var.mkLocalVar VanillaId name ty info
-- Note [Free type variables]
-- | Create a local 'Id' that is marked as exported. This prevents things attached to it from being removed as dead code.
-- | Create a local 'Id' that is marked as exported.
-- This prevents things attached to it from being removed as dead code.
mkExportedLocalId :: Name -> Type -> Id
mkExportedLocalId name ty = mkExportedLocalIdVar name ty vanillaIdInfo
mkExportedLocalId name ty = Var.mkExportedLocalVar VanillaId name ty vanillaIdInfo
-- Note [Free type variables]
-- | Create a system local 'Id'. These are local 'Id's (see "Var#globalvslocal") that are created by the compiler out of thin air
-- | Create a system local 'Id'. These are local 'Id's (see "Var#globalvslocal")
-- that are created by the compiler out of thin air
mkSysLocal :: FastString -> Unique -> Type -> Id
mkSysLocal fs uniq ty = mkLocalId (mkSystemVarName uniq fs) ty
......@@ -309,29 +306,6 @@ mkTemplateLocalsNum n tys = zipWith mkTemplateLocal [n..] tys
\end{code}
%************************************************************************
%* *
\subsection{Basic predicates on @Id@s}
%* *
%************************************************************************
\begin{code}
isId :: Id -> Bool
isId = isIdVar
-- | For an explanation of global vs. local 'Id's, see "Var#globalvslocal"
isLocalId :: Id -> Bool
isLocalId = isLocalIdVar
-- | For an explanation of global vs. local 'Id's, see "Var#globalvslocal"
isGlobalId :: Id -> Bool
isGlobalId = isGlobalIdVar
-- | Determines whether an 'Id' is marked as exported and hence will not be considered dead code
isExportedId :: Id -> Bool
isExportedId = isExportedIdVar
\end{code}
%************************************************************************
%* *
\subsection{Special Ids}
......@@ -342,8 +316,8 @@ isExportedId = isExportedIdVar
-- | If the 'Id' is that for a record selector, extract the 'sel_tycon' and label. Panic otherwise
recordSelectorFieldLabel :: Id -> (TyCon, FieldLabel)
recordSelectorFieldLabel id
= case globalIdDetails id of
RecordSelId { sel_tycon = tycon, sel_label = lbl } -> (tycon,lbl)
= case Var.idDetails id of
RecSelId { sel_tycon = tycon } -> (tycon, idName id)
_ -> panic "recordSelectorFieldLabel"
isRecordSelector :: Id -> Bool
......@@ -357,44 +331,44 @@ isPrimOpId_maybe :: Id -> Maybe PrimOp
isFCallId_maybe :: Id -> Maybe ForeignCall
isDataConWorkId_maybe :: Id -> Maybe DataCon
isRecordSelector id = case globalIdDetails id of
RecordSelId {} -> True
isRecordSelector id = case Var.idDetails id of
RecSelId {} -> True
_ -> False
isNaughtyRecordSelector id = case globalIdDetails id of
RecordSelId { sel_naughty = n } -> n
isNaughtyRecordSelector id = case Var.idDetails id of
RecSelId { sel_naughty = n } -> n
_ -> False
isClassOpId_maybe id = case globalIdDetails id of
isClassOpId_maybe id = case Var.idDetails id of
ClassOpId cls -> Just cls
_other -> Nothing
isPrimOpId id = case globalIdDetails id of
isPrimOpId id = case Var.idDetails id of
PrimOpId _ -> True
_ -> False
isPrimOpId_maybe id = case globalIdDetails id of
isPrimOpId_maybe id = case Var.idDetails id of
PrimOpId op -> Just op
_ -> Nothing
isFCallId id = case globalIdDetails id of
isFCallId id = case Var.idDetails id of
FCallId _ -> True
_ -> False
isFCallId_maybe id = case globalIdDetails id of
isFCallId_maybe id = case Var.idDetails id of
FCallId call -> Just call
_ -> Nothing
isDataConWorkId id = case globalIdDetails id of
isDataConWorkId id = case Var.idDetails id of
DataConWorkId _ -> True
_ -> False
isDataConWorkId_maybe id = case globalIdDetails id of
isDataConWorkId_maybe id = case Var.idDetails id of
DataConWorkId con -> Just con
_ -> Nothing
isDataConId_maybe :: Id -> Maybe DataCon
isDataConId_maybe id = case globalIdDetails id of
isDataConId_maybe id = case Var.idDetails id of
DataConWorkId con -> Just con
DataConWrapId con -> Just con
_ -> Nothing
......@@ -417,7 +391,7 @@ hasNoBinding :: Id -> Bool
-- they aren't any more. Instead, we inject a binding for
-- them at the CorePrep stage.
-- EXCEPT: unboxed tuples, which definitely have no binding
hasNoBinding id = case globalIdDetails id of
hasNoBinding id = case Var.idDetails id of
PrimOpId _ -> True -- See Note [Primop wrappers]
FCallId _ -> True
DataConWorkId dc -> isUnboxedTupleCon dc
......@@ -428,11 +402,10 @@ isImplicitId :: Id -> Bool
-- declarations, so we don't need to put its signature in an interface
-- file, even if it's mentioned in some other interface unfolding.
isImplicitId id
= case globalIdDetails id of
RecordSelId {} -> True
= case Var.idDetails id of
FCallId _ -> True
ClassOpId _ -> True
PrimOpId _ -> True
ClassOpId _ -> True
DataConWorkId _ -> True
DataConWrapId _ -> True
-- These are are implied by their type or class decl;
......@@ -469,13 +442,13 @@ isDeadBinder bndr | isId bndr = isDeadOcc (idOccInfo bndr)
\begin{code}
isTickBoxOp :: Id -> Bool
isTickBoxOp id =
case globalIdDetails id of
case Var.idDetails id of
TickBoxOpId _ -> True
_ -> False
isTickBoxOp_maybe :: Id -> Maybe TickBoxOp
isTickBoxOp_maybe id =
case globalIdDetails id of
case Var.idDetails id of
TickBoxOpId tick -> Just tick
_ -> Nothing
\end{code}
......
......@@ -9,8 +9,8 @@ Haskell. [WDP 94/11])
\begin{code}
module IdInfo (
-- * The GlobalIdDetails type
GlobalIdDetails(..), notGlobalId, -- Not abstract
-- * The IdDetails type
IdDetails(..), pprIdDetails,
-- * The IdInfo type
IdInfo, -- Abstract
......@@ -234,31 +234,23 @@ seqNewDemandInfo (Just dmd) = seqDemand dmd
%************************************************************************
%* *
\subsection{GlobalIdDetails}
IdDetails
%* *
%************************************************************************
This type is here (rather than in Id.lhs) mainly because there's
an IdInfo.hi-boot, but no Id.hi-boot, and GlobalIdDetails is imported
(recursively) by Var.lhs.
\begin{code}
-- | Information pertaining to global 'Id's. See "Var#globalvslocal" for the distinction
-- between global and local in this context
data GlobalIdDetails
= VanillaGlobal -- ^ The 'Id' is imported from elsewhere or is a default method 'Id'
-- | The 'IdDetails' of an 'Id' give stable, and necessary,
-- information about the Id.
data IdDetails
= VanillaId
-- | The 'Id' for a record selector
| RecordSelId
| RecSelId
{ sel_tycon :: TyCon -- ^ For a data type family, this is the /instance/ 'TyCon'
-- not the family 'TyCon'
, sel_label :: FieldLabel
, sel_naughty :: Bool -- True <=> a "naughty" selector which can't actually exist, for example @x@ in:
--
-- > data T = forall a. MkT { x :: a }
}
-- See Note [Naughty record selectors]
-- with MkId.mkRecordSelectorId
-- data T = forall a. MkT { x :: a }
} -- See Note [Naughty record selectors] in TcTyClsDecls
| DataConWorkId DataCon -- ^ The 'Id' is for a data constructor /worker/
| DataConWrapId DataCon -- ^ The 'Id' is for a data constructor /wrapper/
......@@ -275,25 +267,29 @@ data GlobalIdDetails
| TickBoxOpId TickBoxOp -- ^ The 'Id' is for a HPC tick box (both traditional and binary)
| NotGlobalId -- ^ Used as a convenient extra return value from 'globalIdDetails'
-- | An entirely unhelpful 'GlobalIdDetails'
notGlobalId :: GlobalIdDetails
notGlobalId = NotGlobalId
instance Outputable GlobalIdDetails where
ppr NotGlobalId = ptext (sLit "[***NotGlobalId***]")
ppr VanillaGlobal = ptext (sLit "[GlobalId]")
ppr (DataConWorkId _) = ptext (sLit "[DataCon]")
ppr (DataConWrapId _) = ptext (sLit "[DataConWrapper]")
ppr (ClassOpId _) = ptext (sLit "[ClassOp]")
ppr (PrimOpId _) = ptext (sLit "[PrimOp]")
ppr (FCallId _) = ptext (sLit "[ForeignCall]")
ppr (TickBoxOpId _) = ptext (sLit "[TickBoxOp]")
ppr (RecordSelId {}) = ptext (sLit "[RecSel]")
| DFunId -- ^ A dictionary function. We don't use this in an essential way,
-- currently, but it's kind of nice that we can keep track of
-- which Ids are DFuns, across module boundaries too
instance Outputable IdDetails where
ppr = pprIdDetails
pprIdDetails :: IdDetails -> SDoc
pprIdDetails VanillaId = empty
pprIdDetails (RecSelId {}) = ptext (sLit "[RecSel]")
pprIdDetails (DataConWorkId _) = ptext (sLit "[DataCon]")
pprIdDetails (DataConWrapId _) = ptext (sLit "[DataConWrapper]")
pprIdDetails (ClassOpId _) = ptext (sLit "[ClassOp]")
pprIdDetails (PrimOpId _) = ptext (sLit "[PrimOp]")
pprIdDetails (FCallId _) = ptext (sLit "[ForeignCall]")
pprIdDetails (TickBoxOpId _) = ptext (sLit "[TickBoxOp]")
pprIdDetails DFunId = ptext (sLit "[DFunId]")
\end{code}
%************************************************************************
%* *
\subsection{The main IdInfo type}
......
\begin{code}
module IdInfo where
import Outputable
data IdInfo
data GlobalIdDetails
data IdDetails
notGlobalId :: GlobalIdDetails
seqIdInfo :: IdInfo -> ()
pprIdDetails :: IdDetails -> SDoc
\end{code}
\ No newline at end of file
This diff is collapsed.
......@@ -28,21 +28,22 @@ module Var (
-- * The main data type
Var,
-- ** Constructing 'Var's
mkLocalIdVar, mkExportedLocalIdVar, mkGlobalIdVar,
-- ** Taking 'Var's apart
varName, varUnique, varType, varIdInfo, globalIdVarDetails,
varName, varUnique, varType,
-- ** Modifying 'Var's
setVarName, setVarUnique, setVarType,
setIdVarExported, setIdVarNotExported,
globaliseIdVar, lazySetVarIdInfo,
-- ** Constructing, taking apart, modifying 'Id's
mkGlobalVar, mkLocalVar, mkExportedLocalVar,
idInfo, idDetails,
lazySetIdInfo, setIdDetails, globaliseId,
setIdExported, setIdNotExported,
-- ** Predicates
isCoVar, isIdVar, isTyVar, isTcTyVar,
isLocalVar, isLocalIdVar,
isGlobalIdVar, isExportedIdVar,
isCoVar, isId, isTyVar, isTcTyVar,
isLocalVar, isLocalId,
isGlobalId, isExportedId,
mustHaveLocalBinding,
-- * Type variable data type
......@@ -77,8 +78,7 @@ module Var (
import {-# SOURCE #-} TypeRep( Type, Kind )
import {-# SOURCE #-} TcType( TcTyVarDetails, pprTcTyVarDetails )
import {-# SOURCE #-} IdInfo( GlobalIdDetails, notGlobalId,
IdInfo )
import {-# SOURCE #-} IdInfo( IdDetails, IdInfo, pprIdDetails )
import {-# SOURCE #-} TypeRep( isCoercionKind )
import Name hiding (varName)
......@@ -122,25 +122,22 @@ data Var
varType :: Kind,
tcTyVarDetails :: TcTyVarDetails }
| GlobalId { -- Used for imported Ids, dict selectors etc
-- See Note [GlobalId/LocalId] below
varName :: !Name, -- Always an External or WiredIn Name
realUnique :: FastInt,
varType :: Type,
idInfo_ :: IdInfo,
gblDetails :: GlobalIdDetails }
| LocalId { -- Used for locally-defined Ids
-- See Note [GlobalId/LocalId] below
| Id {
varName :: !Name,
realUnique :: FastInt,
varType :: Type,
idInfo_ :: IdInfo,
lclDetails :: LocalIdDetails }
idScope :: IdScope,
idDetails :: IdDetails, -- Stable, doesn't change
idInfo :: IdInfo } -- Unstable, updated by simplifier
data LocalIdDetails
data IdScope -- See Note [GlobalId/LocalId]
= GlobalId
| LocalId ExportFlag
data ExportFlag
= NotExported -- ^ Not exported: may be discarded as dead code.
| Exported -- ^ Exported: kept alive
\end{code}
Note [GlobalId/LocalId]
......@@ -162,13 +159,17 @@ After CoreTidy, top-level LocalIds are turned into GlobalIds
\begin{code}
instance Outputable Var where
ppr var = ppr (varName var) <+> ifPprDebug (brackets extra)
where
extra = case var of
GlobalId {} -> ptext (sLit "gid")
LocalId {} -> ptext (sLit "lid")
TyVar {} -> ptext (sLit "tv")
TcTyVar {tcTyVarDetails = details} -> pprTcTyVarDetails details
ppr var = ppr (varName var) <+> ifPprDebug (brackets (ppr_debug var))
ppr_debug :: Var -> SDoc
ppr_debug (TyVar {}) = ptext (sLit "tv")
ppr_debug (TcTyVar {tcTyVarDetails = d}) = pprTcTyVarDetails d
ppr_debug (Id { idScope = s, idDetails = d }) = ppr_id_scope s <> pprIdDetails d
ppr_id_scope :: IdScope -> SDoc
ppr_id_scope GlobalId = ptext (sLit "gid")
ppr_id_scope (LocalId Exported) = ptext (sLit "lidx")
ppr_id_scope (LocalId NotExported) = ptext (sLit "lid")
instance Show Var where
showsPrec p var = showsPrecSDoc p (ppr var)
......@@ -207,33 +208,6 @@ setVarName var new_name
setVarType :: Id -> Type -> Id
setVarType id ty = id { varType = ty }
setIdVarExported :: Var -> Var
-- ^ Exports the given local 'Id'. Can also be called on global 'Id's, such as data constructors
-- and class operations, which are born as global 'Id's and automatically exported
setIdVarExported id@(LocalId {}) = id { lclDetails = Exported }
setIdVarExported other_id = ASSERT( isIdVar other_id ) other_id
setIdVarNotExported :: Id -> Id
-- ^ We can only do this to LocalIds
setIdVarNotExported id = ASSERT( isLocalIdVar id ) id { lclDetails = NotExported }
globaliseIdVar :: GlobalIdDetails -> Var -> Var
-- ^ If it's a local, make it global
globaliseIdVar details id = GlobalId { varName = varName id,
realUnique = realUnique id,
varType = varType id,
idInfo_ = varIdInfo id,
gblDetails = details }
-- | Extract 'Id' information from the 'Var' if it represents a global or local 'Id', otherwise panic
varIdInfo :: Var -> IdInfo
varIdInfo (GlobalId {idInfo_ = info}) = info
varIdInfo (LocalId {idInfo_ = info}) = info
varIdInfo other_var = pprPanic "idInfo" (ppr other_var)
lazySetVarIdInfo :: Var -> IdInfo -> Var
lazySetVarIdInfo id info = id { idInfo_ = info }
\end{code}
......@@ -322,12 +296,57 @@ mkWildCoVar = mkCoVar (mkSysTvName (mkBuiltinUnique 1) (fsLit "co_wild"))
%************************************************************************
\begin{code}
-- These synonyms are here and not in Id because otherwise we need a very
-- large number of SOURCE imports of Id.hs :-(
type Id = Var
type DictId = Var
-- The next three have a 'Var' suffix even though they always build
-- Ids, becuase Id.lhs uses 'mkGlobalId' etc with different types
mkGlobalVar :: IdDetails -> Name -> Type -> IdInfo -> Id
mkGlobalVar details name ty info
= mk_id name ty GlobalId details info
mkLocalVar :: IdDetails -> Name -> Type -> IdInfo -> Id
mkLocalVar details name ty info
= mk_id name ty (LocalId NotExported) details info
-- | Exported 'Var's will not be removed as dead code
mkExportedLocalVar :: IdDetails -> Name -> Type -> IdInfo -> Id
mkExportedLocalVar details name ty info
= mk_id name ty (LocalId Exported) details info
mk_id :: Name -> Type -> IdScope -> IdDetails -> IdInfo -> Id
mk_id name ty scope details info
= Id { varName = name,
realUnique = getKeyFastInt (nameUnique name),
varType = ty,
idScope = scope,
idDetails = details,
idInfo = info }
-------------------
lazySetIdInfo :: Id -> IdInfo -> Var
lazySetIdInfo id info = id { idInfo = info }
setIdDetails :: Id -> IdDetails -> Id
setIdDetails id details = id { idDetails = details }
globaliseId :: Id -> Id
-- ^ If it's a local, make it global
globaliseId id = id { idScope = GlobalId }
setIdExported :: Id -> Id
-- ^ Exports the given local 'Id'. Can also be called on global 'Id's, such as data constructors
-- and class operations, which are born as global 'Id's and automatically exported
setIdExported id@(Id { idScope = LocalId {} }) = id { idScope = LocalId Exported }
setIdExported id@(Id { idScope = GlobalId }) = id
setIdExported tv = pprPanic "setIdExported" (ppr tv)
setIdNotExported :: Id -> Id
-- ^ We can only do this to LocalIds
setIdNotExported id = ASSERT( isLocalId id )
id { idScope = LocalId NotExported }
\end{code}
%************************************************************************
......@@ -336,33 +355,6 @@ type DictId = Var
%* *
%************************************************************************
\begin{code}
-- | For an explanation of global vs. local 'Var's, see "Var#globalvslocal"
mkGlobalIdVar :: GlobalIdDetails -> Name -> Type -> IdInfo -> Var
mkGlobalIdVar details name ty info
= GlobalId { varName = name,
realUnique = getKeyFastInt (nameUnique name), -- Cache the unique
varType = ty,
gblDetails = details,
idInfo_ = info }
mkLocalIdVar' :: Name -> Type -> LocalIdDetails -> IdInfo -> Var
mkLocalIdVar' name ty details info
= LocalId { varName = name,
realUnique = getKeyFastInt (nameUnique name), -- Cache the unique
varType = ty,
lclDetails = details,
idInfo_ = info }
-- | For an explanation of global vs. local 'Var's, see "Var#globalvslocal"
mkLocalIdVar :: Name -> Type -> IdInfo -> Var
mkLocalIdVar name ty info = mkLocalIdVar' name ty NotExported info
-- | Exported 'Var's will not be removed as dead code
mkExportedLocalIdVar :: Name -> Type -> IdInfo -> Var
mkExportedLocalIdVar name ty info = mkLocalIdVar' name ty Exported info
\end{code}
\begin{code}
isTyVar :: Var -> Bool
isTyVar (TyVar {}) = True
......@@ -373,14 +365,13 @@ isTcTyVar :: Var -> Bool
isTcTyVar (TcTyVar {}) = True
isTcTyVar _ = False
isIdVar :: Var -> Bool
isIdVar (LocalId {}) = True
isIdVar (GlobalId {}) = True
isIdVar _ = False
isId :: Var -> Bool
isId (Id {}) = True
isId _ = False
isLocalIdVar :: Var -> Bool
isLocalIdVar (LocalId {}) = True
isLocalIdVar _ = False
isLocalId :: Var -> Bool
isLocalId (Id { idScope = LocalId _ }) = True
isLocalId _ = False
isCoVar :: Var -> Bool
isCoVar (v@(TyVar {})) = isCoercionVar v
......@@ -391,8 +382,11 @@ isCoVar _ = False
-- These are the variables that we need to pay attention to when finding free
-- variables, or doing dependency analysis.
isLocalVar :: Var -> Bool
isLocalVar (GlobalId {}) = False
isLocalVar _ = True
isLocalVar v = not (isGlobalId v)
isGlobalId :: Var -> Bool