-%
+\%
% (c) The University of Glasgow 2006
% (c) The AQUA Project, Glasgow University, 1998
%
This module contains definitions for the IdInfo for things that
have a standard form, namely:
- * data constructors
- * record selectors
- * method and superclass selectors
- * primitive operations
+* data constructors
+* record selectors
+* method and superclass selectors
+* primitive operations
\begin{code}
-{-# OPTIONS -w #-}
+{-# 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/CodingStyle#Warnings
+-- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
-- for details
module MkId (
- mkDictFunId, mkDefaultMethodId,
- mkDictSelId,
+ mkDictFunId, mkDefaultMethodId,
+ mkDictSelId,
- mkDataConIds,
- mkRecordSelId,
- mkPrimOpId, mkFCallId, mkTickBoxOpId, mkBreakPointOpId,
+ mkDataConIds,
+ mkRecordSelId,
+ mkPrimOpId, mkFCallId, mkTickBoxOpId, mkBreakPointOpId,
- mkReboxingAlt, wrapNewTypeBody, unwrapNewTypeBody,
+ mkReboxingAlt, wrapNewTypeBody, unwrapNewTypeBody,
wrapFamInstBody, unwrapFamInstScrut,
mkUnpackCase, mkProductBox,
- -- And some particular Ids; see below for why they are wired in
- wiredInIds, ghcPrimIds,
- unsafeCoerceId, realWorldPrimId, voidArgId, nullAddrId, seqId,
- lazyId, lazyIdUnfolding, lazyIdKey,
+ -- And some particular Ids; see below for why they are wired in
+ wiredInIds, ghcPrimIds,
+ unsafeCoerceId, realWorldPrimId, voidArgId, nullAddrId, seqId,
+ lazyId, lazyIdUnfolding, lazyIdKey,
- mkRuntimeErrorApp,
- rEC_CON_ERROR_ID, iRREFUT_PAT_ERROR_ID, rUNTIME_ERROR_ID,
- nON_EXHAUSTIVE_GUARDS_ERROR_ID, nO_METHOD_BINDING_ERROR_ID,
- pAT_ERROR_ID, eRROR_ID,
+ mkRuntimeErrorApp,
+ rEC_CON_ERROR_ID, iRREFUT_PAT_ERROR_ID, rUNTIME_ERROR_ID,
+ nON_EXHAUSTIVE_GUARDS_ERROR_ID, nO_METHOD_BINDING_ERROR_ID,
+ pAT_ERROR_ID, eRROR_ID,
unsafeCoerceName
) where
import TysPrim
import TysWiredIn
import PrelRules
+import Unify
import Type
import TypeRep
-import TcGadt
import Coercion
import TcType
import CoreUtils
\end{code}
%************************************************************************
-%* *
+%* *
\subsection{Wired in Ids}
-%* *
+%* *
%************************************************************************
\begin{code}
wiredInIds
- = [ -- These error-y things are wired in because we don't yet have
- -- a way to express in an interface file that the result type variable
- -- is 'open'; that is can be unified with an unboxed type
- --
- -- [The interface file format now carry such information, but there's
- -- no way yet of expressing at the definition site for these
- -- error-reporting functions that they have an 'open'
- -- result type. -- sof 1/99]
-
- eRROR_ID, -- This one isn't used anywhere else in the compiler
- -- But we still need it in wiredInIds so that when GHC
- -- compiles a program that mentions 'error' we don't
- -- import its type from the interface file; we just get
- -- the Id defined here. Which has an 'open-tyvar' type.
+ = [ -- These error-y things are wired in because we don't yet have
+ -- a way to express in an interface file that the result type variable
+ -- is 'open'; that is can be unified with an unboxed type
+ --
+ -- [The interface file format now carry such information, but there's
+ -- no way yet of expressing at the definition site for these
+ -- error-reporting functions that they have an 'open'
+ -- result type. -- sof 1/99]
+
+ eRROR_ID, -- This one isn't used anywhere else in the compiler
+ -- But we still need it in wiredInIds so that when GHC
+ -- compiles a program that mentions 'error' we don't
+ -- import its type from the interface file; we just get
+ -- the Id defined here. Which has an 'open-tyvar' type.
rUNTIME_ERROR_ID,
iRREFUT_PAT_ERROR_ID,
-- These Ids are exported from GHC.Prim
ghcPrimIds
- = [ -- These can't be defined in Haskell, but they have
- -- perfectly reasonable unfoldings in Core
+ = [ -- These can't be defined in Haskell, but they have
+ -- perfectly reasonable unfoldings in Core
realWorldPrimId,
unsafeCoerceId,
nullAddrId,
\end{code}
%************************************************************************
-%* *
+%* *
\subsection{Data constructors}
-%* *
+%* *
%************************************************************************
The wrapper for a constructor is an ordinary top-level binding that evaluates
We're going to build a constructor that looks like:
- data (Data a, C b) => T a b = T1 !a !Int b
+ data (Data a, C b) => T a b = T1 !a !Int b
- T1 = /\ a b ->
- \d1::Data a, d2::C b ->
- \p q r -> case p of { p ->
- case q of { q ->
- Con T1 [a,b] [p,q,r]}}
+ T1 = /\ a b ->
+ \d1::Data a, d2::C b ->
+ \p q r -> case p of { p ->
+ case q of { q ->
+ Con T1 [a,b] [p,q,r]}}
Notice that
The wrapper and worker of MapPair get the types
- -- Wrapper
+ -- Wrapper
$WMapPair :: forall a b v. Map a (Map a b v) -> Map (a, b) v
$WMapPair a b v = MapPair a b v `cast` sym (Co123Map a b v)
- -- Worker
+ -- Worker
MapPair :: forall a b v. Map a (Map a b v) -> :R123Map a b v
This coercion is conditionally applied by wrapFamInstBody.
It's a bit more complicated if the data instance is a GADT as well!
data instance T [a] where
- T1 :: forall b. b -> T [Maybe b]
+ T1 :: forall b. b -> T [Maybe b]
Hence
Co7T a :: T [a] ~ :R7T a
Now we want
- -- Wrapper
+ -- Wrapper
$WT1 :: forall b. b -> T [Maybe b]
$WT1 b v = T1 (Maybe b) b (Maybe b) v
- `cast` sym (Co7T (Maybe b))
+ `cast` sym (Co7T (Maybe b))
- -- Worker
+ -- Worker
T1 :: forall c b. (c ~ Maybe b) => b -> :R7T c
\begin{code}
mkDataConIds :: Name -> Name -> DataCon -> DataConIds
mkDataConIds wrap_name wkr_name data_con
- | isNewTyCon tycon -- Newtype, only has a worker
+ | isNewTyCon tycon -- Newtype, only has a worker
= DCIds Nothing nt_work_id
- | any isMarkedStrict all_strict_marks -- Algebraic, needs wrapper
- || not (null eq_spec) -- NB: LoadIface.ifaceDeclSubBndrs
- || isFamInstTyCon tycon -- depends on this test
+ | any isMarkedStrict all_strict_marks -- Algebraic, needs wrapper
+ || not (null eq_spec) -- NB: LoadIface.ifaceDeclSubBndrs
+ || isFamInstTyCon tycon -- depends on this test
= DCIds (Just alg_wrap_id) wrk_id
- | otherwise -- Algebraic, no wrapper
+ | otherwise -- Algebraic, no wrapper
= DCIds Nothing wrk_id
where
(univ_tvs, ex_tvs, eq_spec,
eq_theta, dict_theta, orig_arg_tys, res_ty) = dataConFullSig data_con
- tycon = dataConTyCon data_con -- The representation TyCon (not family)
+ tycon = dataConTyCon data_con -- The representation TyCon (not family)
- ----------- Worker (algebraic data types only) --------------
- -- The *worker* for the data constructor is the function that
- -- takes the representation arguments and builds the constructor.
+ ----------- Worker (algebraic data types only) --------------
+ -- The *worker* for the data constructor is the function that
+ -- takes the representation arguments and builds the constructor.
wrk_id = mkGlobalId (DataConWorkId data_con) wkr_name
- (dataConRepType data_con) wkr_info
+ (dataConRepType data_con) wkr_info
wkr_arity = dataConRepArity data_con
wkr_info = noCafIdInfo
- `setArityInfo` wkr_arity
- `setAllStrictnessInfo` Just wkr_sig
- `setUnfoldingInfo` evaldUnfolding -- Record that it's evaluated,
- -- even if arity = 0
+ `setArityInfo` wkr_arity
+ `setAllStrictnessInfo` Just wkr_sig
+ `setUnfoldingInfo` evaldUnfolding -- Record that it's evaluated,
+ -- even if arity = 0
wkr_sig = mkStrictSig (mkTopDmdType (replicate wkr_arity topDmd) cpr_info)
- -- Note [Data-con worker strictness]
- -- Notice that we do *not* say the worker is strict
- -- even if the data constructor is declared strict
- -- e.g. data T = MkT !(Int,Int)
- -- Why? Because the *wrapper* is strict (and its unfolding has case
- -- expresssions that do the evals) but the *worker* itself is not.
- -- If we pretend it is strict then when we see
- -- case x of y -> $wMkT y
- -- the simplifier thinks that y is "sure to be evaluated" (because
- -- $wMkT is strict) and drops the case. No, $wMkT is not strict.
- --
- -- When the simplifer sees a pattern
- -- case e of MkT x -> ...
- -- it uses the dataConRepStrictness of MkT to mark x as evaluated;
- -- but that's fine... dataConRepStrictness comes from the data con
- -- not from the worker Id.
+ -- Note [Data-con worker strictness]
+ -- Notice that we do *not* say the worker is strict
+ -- even if the data constructor is declared strict
+ -- e.g. data T = MkT !(Int,Int)
+ -- Why? Because the *wrapper* is strict (and its unfolding has case
+ -- expresssions that do the evals) but the *worker* itself is not.
+ -- If we pretend it is strict then when we see
+ -- case x of y -> $wMkT y
+ -- the simplifier thinks that y is "sure to be evaluated" (because
+ -- $wMkT is strict) and drops the case. No, $wMkT is not strict.
+ --
+ -- When the simplifer sees a pattern
+ -- case e of MkT x -> ...
+ -- it uses the dataConRepStrictness of MkT to mark x as evaluated;
+ -- but that's fine... dataConRepStrictness comes from the data con
+ -- not from the worker Id.
cpr_info | isProductTyCon tycon &&
- isDataTyCon tycon &&
- wkr_arity > 0 &&
- wkr_arity <= mAX_CPR_SIZE = retCPR
- | otherwise = TopRes
- -- RetCPR is only true for products that are real data types;
- -- that is, not unboxed tuples or [non-recursive] newtypes
-
- ----------- Workers for newtypes --------------
+ isDataTyCon tycon &&
+ wkr_arity > 0 &&
+ wkr_arity <= mAX_CPR_SIZE = retCPR
+ | otherwise = TopRes
+ -- RetCPR is only true for products that are real data types;
+ -- that is, not unboxed tuples or [non-recursive] newtypes
+
+ ----------- Workers for newtypes --------------
nt_work_id = mkGlobalId (DataConWrapId data_con) wkr_name wrap_ty nt_work_info
- nt_work_info = noCafIdInfo -- The NoCaf-ness is set by noCafIdInfo
- `setArityInfo` 1 -- Arity 1
- `setUnfoldingInfo` newtype_unf
+ nt_work_info = noCafIdInfo -- The NoCaf-ness is set by noCafIdInfo
+ `setArityInfo` 1 -- Arity 1
+ `setUnfoldingInfo` newtype_unf
newtype_unf = -- The assertion below is no longer correct:
- -- there may be a dict theta rather than a singleton orig_arg_ty
- -- ASSERT( isVanillaDataCon data_con &&
- -- isSingleton orig_arg_tys )
- --
- -- No existentials on a newtype, but it can have a context
- -- e.g. newtype Eq a => T a = MkT (...)
- mkCompulsoryUnfolding $
- mkLams wrap_tvs $ Lam id_arg1 $
- wrapNewTypeBody tycon res_ty_args
+ -- there may be a dict theta rather than a singleton orig_arg_ty
+ -- ASSERT( isVanillaDataCon data_con &&
+ -- isSingleton orig_arg_tys )
+ --
+ -- No existentials on a newtype, but it can have a context
+ -- e.g. newtype Eq a => T a = MkT (...)
+ mkCompulsoryUnfolding $
+ mkLams wrap_tvs $ Lam id_arg1 $
+ wrapNewTypeBody tycon res_ty_args
(Var id_arg1)
id_arg1 = mkTemplateLocal 1
- (if null orig_arg_tys
- then ASSERT(not (null $ dataConDictTheta data_con)) mkPredTy $ head (dataConDictTheta data_con)
- else head orig_arg_tys
- )
-
- ----------- Wrapper --------------
- -- We used to include the stupid theta in the wrapper's args
- -- but now we don't. Instead the type checker just injects these
- -- extra constraints where necessary.
+ (if null orig_arg_tys
+ then ASSERT(not (null $ dataConDictTheta data_con)) mkPredTy $ head (dataConDictTheta data_con)
+ else head orig_arg_tys
+ )
+
+ ----------- Wrapper --------------
+ -- We used to include the stupid theta in the wrapper's args
+ -- but now we don't. Instead the type checker just injects these
+ -- extra constraints where necessary.
wrap_tvs = (univ_tvs `minusList` map fst eq_spec) ++ ex_tvs
- res_ty_args = substTyVars (mkTopTvSubst eq_spec) univ_tvs
+ res_ty_args = substTyVars (mkTopTvSubst eq_spec) univ_tvs
eq_tys = mkPredTys eq_theta
dict_tys = mkPredTys dict_theta
wrap_ty = mkForAllTys wrap_tvs $ mkFunTys eq_tys $ mkFunTys dict_tys $
- mkFunTys orig_arg_tys $ res_ty
- -- NB: watch out here if you allow user-written equality
- -- constraints in data constructor signatures
+ mkFunTys orig_arg_tys $ res_ty
+ -- NB: watch out here if you allow user-written equality
+ -- constraints in data constructor signatures
- ----------- Wrappers for algebraic data types --------------
+ ----------- Wrappers for algebraic data types --------------
alg_wrap_id = mkGlobalId (DataConWrapId data_con) wrap_name wrap_ty alg_wrap_info
- alg_wrap_info = noCafIdInfo -- The NoCaf-ness is set by noCafIdInfo
- `setArityInfo` wrap_arity
- -- It's important to specify the arity, so that partial
- -- applications are treated as values
- `setUnfoldingInfo` wrap_unf
- `setAllStrictnessInfo` Just wrap_sig
+ alg_wrap_info = noCafIdInfo -- The NoCaf-ness is set by noCafIdInfo
+ `setArityInfo` wrap_arity
+ -- It's important to specify the arity, so that partial
+ -- applications are treated as values
+ `setUnfoldingInfo` wrap_unf
+ `setAllStrictnessInfo` Just wrap_sig
all_strict_marks = dataConExStricts data_con ++ dataConStrictMarks data_con
wrap_sig = mkStrictSig (mkTopDmdType arg_dmds cpr_info)
arg_dmds = map mk_dmd all_strict_marks
mk_dmd str | isMarkedStrict str = evalDmd
- | otherwise = lazyDmd
- -- The Cpr info can be important inside INLINE rhss, where the
- -- wrapper constructor isn't inlined.
- -- And the argument strictness can be important too; we
- -- may not inline a contructor when it is partially applied.
- -- For example:
- -- data W = C !Int !Int !Int
- -- ...(let w = C x in ...(w p q)...)...
- -- we want to see that w is strict in its two arguments
+ | otherwise = lazyDmd
+ -- The Cpr info can be important inside INLINE rhss, where the
+ -- wrapper constructor isn't inlined.
+ -- And the argument strictness can be important too; we
+ -- may not inline a contructor when it is partially applied.
+ -- For example:
+ -- data W = C !Int !Int !Int
+ -- ...(let w = C x in ...(w p q)...)...
+ -- we want to see that w is strict in its two arguments
wrap_unf = mkTopUnfolding $ Note InlineMe $
- mkLams wrap_tvs $
- mkLams eq_args $
- mkLams dict_args $ mkLams id_args $
- foldr mk_case con_app
- (zip (dict_args ++ id_args) all_strict_marks)
- i3 []
+ mkLams wrap_tvs $
+ mkLams eq_args $
+ mkLams dict_args $ mkLams id_args $
+ foldr mk_case con_app
+ (zip (dict_args ++ id_args) all_strict_marks)
+ i3 []
con_app _ rep_ids = wrapFamInstBody tycon res_ty_args $
- Var wrk_id `mkTyApps` res_ty_args
- `mkVarApps` ex_tvs
- `mkTyApps` map snd eq_spec -- Equality evidence
- `mkVarApps` eq_args
- `mkVarApps` reverse rep_ids
+ Var wrk_id `mkTyApps` res_ty_args
+ `mkVarApps` ex_tvs
+ -- Equality evidence:
+ `mkTyApps` map snd eq_spec
+ `mkVarApps` eq_args
+ `mkVarApps` reverse rep_ids
(dict_args,i2) = mkLocals 1 dict_tys
(id_args,i3) = mkLocals i2 orig_arg_tys
- wrap_arity = i3-1
+ wrap_arity = i3-1
(eq_args,_) = mkCoVarLocals i3 eq_tys
mkCoVarLocals i [] = ([],i)
mkCoVarLocals i (x:xs) = let (ys,j) = mkCoVarLocals (i+1) xs
- y = mkCoVar (mkSysTvName (mkBuiltinUnique i) FSLIT("dc_co")) x
+ y = mkCoVar (mkSysTvName (mkBuiltinUnique i) (fsLit "dc_co")) x
in (y:ys,j)
mk_case
- :: (Id, StrictnessMark) -- Arg, strictness
- -> (Int -> [Id] -> CoreExpr) -- Body
- -> Int -- Next rep arg id
- -> [Id] -- Rep args so far, reversed
- -> CoreExpr
+ :: (Id, StrictnessMark) -- Arg, strictness
+ -> (Int -> [Id] -> CoreExpr) -- Body
+ -> Int -- Next rep arg id
+ -> [Id] -- Rep args so far, reversed
+ -> CoreExpr
mk_case (arg,strict) body i rep_args
- = case strict of
- NotMarkedStrict -> body i (arg:rep_args)
- MarkedStrict
- | isUnLiftedType (idType arg) -> body i (arg:rep_args)
- | otherwise ->
- Case (Var arg) arg res_ty [(DEFAULT,[], body i (arg:rep_args))]
-
- MarkedUnboxed
- -> unboxProduct i (Var arg) (idType arg) the_body
+ = case strict of
+ NotMarkedStrict -> body i (arg:rep_args)
+ MarkedStrict
+ | isUnLiftedType (idType arg) -> body i (arg:rep_args)
+ | otherwise ->
+ Case (Var arg) arg res_ty [(DEFAULT,[], body i (arg:rep_args))]
+
+ MarkedUnboxed
+ -> unboxProduct i (Var arg) (idType arg) the_body
where
the_body i con_args = body i (reverse con_args ++ rep_args)
mAX_CPR_SIZE :: Arity
mAX_CPR_SIZE = 10
-- We do not treat very big tuples as CPR-ish:
--- a) for a start we get into trouble because there aren't
--- "enough" unboxed tuple types (a tiresome restriction,
--- but hard to fix),
--- b) more importantly, big unboxed tuples get returned mainly
--- on the stack, and are often then allocated in the heap
--- by the caller. So doing CPR for them may in fact make
--- things worse.
+-- a) for a start we get into trouble because there aren't
+-- "enough" unboxed tuple types (a tiresome restriction,
+-- but hard to fix),
+-- b) more importantly, big unboxed tuples get returned mainly
+-- on the stack, and are often then allocated in the heap
+-- by the caller. So doing CPR for them may in fact make
+-- things worse.
mkLocals i tys = (zipWith mkTemplateLocal [i..i+n-1] tys, i+n)
- where
- n = length tys
+ where
+ n = length tys
\end{code}
%************************************************************************
-%* *
+%* *
\subsection{Record selectors}
-%* *
+%* *
%************************************************************************
We're going to build a record selector unfolding that looks like this:
- data T a b c = T1 { ..., op :: a, ...}
- | T2 { ..., op :: a, ...}
- | T3
+ data T a b c = T1 { ..., op :: a, ...}
+ | T2 { ..., op :: a, ...}
+ | T3
- sel = /\ a b c -> \ d -> case d of
- T1 ... x ... -> x
- T2 ... x ... -> x
- other -> error "..."
+ sel = /\ a b c -> \ d -> case d of
+ T1 ... x ... -> x
+ T2 ... x ... -> x
+ other -> error "..."
Similarly for newtypes
- newtype N a = MkN { unN :: a->a }
+ newtype N a = MkN { unN :: a->a }
- unN :: N a -> a -> a
- unN n = coerce (a->a) n
-
+ unN :: N a -> a -> a
+ unN n = coerce (a->a) n
+
We need to take a little care if the field has a polymorphic type:
- data R = R { f :: forall a. a->a }
+ data R = R { f :: forall a. a->a }
Then we want
- f :: forall a. R -> a -> a
- f = /\ a \ r = case r of
- R f -> f a
+ f :: forall a. R -> a -> a
+ f = /\ a \ r = case r of
+ R f -> f a
(not f :: R -> forall a. a->a, which gives the type inference mechanism
problems at call sites)
Similarly for (recursive) newtypes
- newtype N = MkN { unN :: forall a. a->a }
+ newtype N = MkN { unN :: forall a. a->a }
- unN :: forall b. N -> b -> b
- unN = /\b -> \n:N -> (coerce (forall a. a->a) n)
+ unN :: forall b. N -> b -> b
+ unN = /\b -> \n:N -> (coerce (forall a. a->a) n)
Note [Naughty record selectors]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A "naughty" field is one for which we can't define a record
selector, because an existential type variable would escape. For example:
- data T = forall a. MkT { x,y::a }
-We obviously can't define
- x (MkT v _) = v
+ data T = forall a. MkT { x,y::a }
+We obviously can't define
+ x (MkT v _) = v
Nevertheless we *do* put a RecordSelId into the type environment
so that if the user tries to use 'x' as a selector we can bleat
helpfully, rather than saying unhelpfully that 'x' is not in scope.
For GADTs, we require that all constructors with a common field 'f' have the same
result type (modulo alpha conversion). [Checked in TcTyClsDecls.checkValidTyCon]
E.g.
- data T where
- T1 { f :: a } :: T [a]
- T2 { f :: a, y :: b } :: T [a]
+ data T where
+ T1 { f :: a } :: T [a]
+ T2 { f :: a, y :: b } :: T [a]
and now the selector takes that type as its argument:
- f :: forall a. T [a] -> a
- f t = case t of
- T1 { f = v } -> v
- T2 { f = v } -> v
+ f :: forall a. T [a] -> a
+ f t = case t of
+ T1 { f = v } -> v
+ T2 { f = v } -> v
Note the forall'd tyvars of the selector are just the free tyvars
of the result type; there may be other tyvars in the constructor's
type (e.g. 'b' in T2).
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It's OK to combine GADTs and type families. Here's a running example:
- data instance T [a] where
- T1 { fld :: b } :: T [Maybe b]
+ data instance T [a] where
+ T1 { fld :: b } :: T [Maybe b]
The representation type looks like this
- data :R7T a where
- T1 { fld :: b } :: :R7T (Maybe b)
+ data :R7T a where
+ T1 { fld :: b } :: :R7T (Maybe b)
and there's coercion from the family type to the representation type
- :CoR7T a :: T [a] ~ :R7T a
+ :CoR7T a :: T [a] ~ :R7T a
The selector we want for fld looks like this:
- fld :: forall b. T [Maybe b] -> b
- fld = /\b. \(d::T [Maybe b]).
- case d `cast` :CoR7T (Maybe b) of
- T1 (x::b) -> x
+ fld :: forall b. T [Maybe b] -> b
+ fld = /\b. \(d::T [Maybe b]).
+ case d `cast` :CoR7T (Maybe b) of
+ T1 (x::b) -> x
The scrutinee of the case has type :R7T (Maybe b), which can be
gotten by appying the eq_spec to the univ_tvs of the data con.
\begin{code}
mkRecordSelId :: TyCon -> FieldLabel -> Id
mkRecordSelId tycon field_label
- -- Assumes that all fields with the same field label have the same type
- | is_naughty = naughty_id
- | otherwise = sel_id
+ -- Assumes that all fields with the same field label have the same type
+ = sel_id
where
- is_naughty = not (tyVarsOfType field_ty `subVarSet` data_tv_set)
- sel_id_details = RecordSelId { sel_tycon = tycon, sel_label = field_label, sel_naughty = is_naughty }
- -- For a data type family, the tycon is the *instance* TyCon
-
- -- Escapist case here for naughty constructors
- -- We give it no IdInfo, and a type of forall a.a (never looked at)
- naughty_id = mkGlobalId sel_id_details field_label forall_a_a noCafIdInfo
+ -- Because this function gets called by implicitTyThings, we need to
+ -- produce the OccName of the Id without doing any suspend type checks.
+ -- (see the note [Tricky iface loop]).
+ -- A suspended type-check is sometimes necessary to compute field_ty,
+ -- so we need to make sure that we suspend anything that depends on field_ty.
+
+ -- the overall result
+ sel_id = mkGlobalId sel_id_details field_label theType theInfo
+
+ -- check whether the type is naughty: this thunk does not get forced
+ -- until the type is actually needed
+ field_ty = dataConFieldType con1 field_label
+ is_naughty = not (tyVarsOfType field_ty `subVarSet` data_tv_set)
+
+ -- it's important that this doesn't force the if
+ (theType, theInfo) = if is_naughty
+ -- Escapist case here for naughty constructors
+ -- We give it no IdInfo, and a type of
+ -- forall a.a (never looked at)
+ then (forall_a_a, noCafIdInfo)
+ -- otherwise do the real case
+ else (selector_ty, info)
+
+ sel_id_details = RecordSelId { sel_tycon = tycon,
+ sel_label = field_label,
+ sel_naughty = is_naughty }
+ -- For a data type family, the tycon is the *instance* TyCon
+
+ -- for naughty case
forall_a_a = mkForAllTy alphaTyVar (mkTyVarTy alphaTyVar)
- -- Normal case starts here
- sel_id = mkGlobalId sel_id_details field_label selector_ty info
- data_cons = tyConDataCons tycon
- data_cons_w_field = filter has_field data_cons -- Can't be empty!
+ -- real case starts here:
+ data_cons = tyConDataCons tycon
+ data_cons_w_field = filter has_field data_cons -- Can't be empty!
has_field con = field_label `elem` dataConFieldLabels con
- con1 = ASSERT( not (null data_cons_w_field) ) head data_cons_w_field
+ con1 = ASSERT( not (null data_cons_w_field) ) head data_cons_w_field
(univ_tvs, _, eq_spec, _, _, _, data_ty) = dataConFullSig con1
- -- For a data type family, the data_ty (and hence selector_ty) mentions
- -- only the family TyCon, not the instance TyCon
- data_tv_set = tyVarsOfType data_ty
- data_tvs = varSetElems data_tv_set
- field_ty = dataConFieldType con1 field_label
+ -- For a data type family, the data_ty (and hence selector_ty) mentions
+ -- only the family TyCon, not the instance TyCon
+ data_tv_set = tyVarsOfType data_ty
+ data_tvs = varSetElems data_tv_set
- -- *Very* tiresomely, the selectors are (unnecessarily!) overloaded over
- -- just the dictionaries in the types of the constructors that contain
- -- the relevant field. [The Report says that pattern matching on a
- -- constructor gives the same constraints as applying it.] Urgh.
- --
- -- However, not all data cons have all constraints (because of
- -- BuildTyCl.mkDataConStupidTheta). So we need to find all the data cons
- -- involved in the pattern match and take the union of their constraints.
+ -- *Very* tiresomely, the selectors are (unnecessarily!) overloaded over
+ -- just the dictionaries in the types of the constructors that contain
+ -- the relevant field. [The Report says that pattern matching on a
+ -- constructor gives the same constraints as applying it.] Urgh.
+ --
+ -- However, not all data cons have all constraints (because of
+ -- BuildTyCl.mkDataConStupidTheta). So we need to find all the data cons
+ -- involved in the pattern match and take the union of their constraints.
stupid_dict_tys = mkPredTys (dataConsStupidTheta data_cons_w_field)
n_stupid_dicts = length stupid_dict_tys
field_theta = filter (not . isEqPred) pre_field_theta
field_dict_tys = mkPredTys field_theta
n_field_dict_tys = length field_dict_tys
- -- If the field has a universally quantified type we have to
- -- be a bit careful. Suppose we have
- -- data R = R { op :: forall a. Foo a => a -> a }
- -- Then we can't give op the type
- -- op :: R -> forall a. Foo a => a -> a
- -- because the typechecker doesn't understand foralls to the
- -- right of an arrow. The "right" type to give it is
- -- op :: forall a. Foo a => R -> a -> a
- -- But then we must generate the right unfolding too:
- -- op = /\a -> \dfoo -> \ r ->
- -- case r of
- -- R op -> op a dfoo
- -- Note that this is exactly the type we'd infer from a user defn
- -- op (R op) = op
+ -- If the field has a universally quantified type we have to
+ -- be a bit careful. Suppose we have
+ -- data R = R { op :: forall a. Foo a => a -> a }
+ -- Then we can't give op the type
+ -- op :: R -> forall a. Foo a => a -> a
+ -- because the typechecker doesn't understand foralls to the
+ -- right of an arrow. The "right" type to give it is
+ -- op :: forall a. Foo a => R -> a -> a
+ -- But then we must generate the right unfolding too:
+ -- op = /\a -> \dfoo -> \ r ->
+ -- case r of
+ -- R op -> op a dfoo
+ -- Note that this is exactly the type we'd infer from a user defn
+ -- op (R op) = op
selector_ty :: Type
selector_ty = mkForAllTys data_tvs $ mkForAllTys field_tyvars $
- mkFunTys stupid_dict_tys $ mkFunTys field_dict_tys $
- mkFunTy data_ty field_tau
+ mkFunTys stupid_dict_tys $ mkFunTys field_dict_tys $
+ mkFunTy data_ty field_tau
arity = 1 + n_stupid_dicts + n_field_dict_tys
(strict_sig, rhs_w_str) = dmdAnalTopRhs sel_rhs
- -- Use the demand analyser to work out strictness.
- -- With all this unpackery it's not easy!
+ -- Use the demand analyser to work out strictness.
+ -- With all this unpackery it's not easy!
info = noCafIdInfo
- `setCafInfo` caf_info
- `setArityInfo` arity
- `setUnfoldingInfo` mkTopUnfolding rhs_w_str
- `setAllStrictnessInfo` Just strict_sig
-
- -- Allocate Ids. We do it a funny way round because field_dict_tys is
- -- almost always empty. Also note that we use max_dict_tys
- -- rather than n_dict_tys, because the latter gives an infinite loop:
- -- n_dict tys depends on the_alts, which depens on arg_ids, which depends
- -- on arity, which depends on n_dict tys. Sigh! Mega sigh!
+ `setCafInfo` caf_info
+ `setArityInfo` arity
+ `setUnfoldingInfo` mkTopUnfolding rhs_w_str
+ `setAllStrictnessInfo` Just strict_sig
+
+ -- Allocate Ids. We do it a funny way round because field_dict_tys is
+ -- almost always empty. Also note that we use max_dict_tys
+ -- rather than n_dict_tys, because the latter gives an infinite loop:
+ -- n_dict tys depends on the_alts, which depens on arg_ids, which
+ -- depends on arity, which depends on n_dict tys. Sigh! Mega sigh!
stupid_dict_ids = mkTemplateLocalsNum 1 stupid_dict_tys
max_stupid_dicts = length (tyConStupidTheta tycon)
field_dict_base = max_stupid_dicts + 1
field_dict_ids = mkTemplateLocalsNum field_dict_base field_dict_tys
dict_id_base = field_dict_base + n_field_dict_tys
- data_id = mkTemplateLocal dict_id_base data_ty
- scrut_id = mkTemplateLocal (dict_id_base+1) scrut_ty
- arg_base = dict_id_base + 2
+ data_id = mkTemplateLocal dict_id_base data_ty
+ scrut_id = mkTemplateLocal (dict_id_base+1) scrut_ty
+ arg_base = dict_id_base + 2
the_alts :: [CoreAlt]
- the_alts = map mk_alt data_cons_w_field -- Already sorted by data-con
- no_default = length data_cons == length data_cons_w_field -- No default needed
+ the_alts = map mk_alt data_cons_w_field -- Already sorted by data-con
+ no_default = length data_cons == length data_cons_w_field -- No default needed
default_alt | no_default = []
- | otherwise = [(DEFAULT, [], error_expr)]
+ | otherwise = [(DEFAULT, [], error_expr)]
- -- The default branch may have CAF refs, because it calls recSelError etc.
+ -- The default branch may have CAF refs, because it calls recSelError etc.
caf_info | no_default = NoCafRefs
- | otherwise = MayHaveCafRefs
+ | otherwise = MayHaveCafRefs
sel_rhs = mkLams data_tvs $ mkLams field_tyvars $
- mkLams stupid_dict_ids $ mkLams field_dict_ids $
- Lam data_id $ mk_result sel_body
+ mkLams stupid_dict_ids $ mkLams field_dict_ids $
+ Lam data_id $ mk_result sel_body
scrut_ty_args = substTyVars (mkTopTvSubst eq_spec) univ_tvs
- scrut_ty = mkTyConApp tycon scrut_ty_args
+ scrut_ty = mkTyConApp tycon scrut_ty_args
scrut = unwrapFamInstScrut tycon scrut_ty_args (Var data_id)
- -- First coerce from the type family to the representation type
+ -- First coerce from the type family to the representation type
- -- NB: A newtype always has a vanilla DataCon; no existentials etc
- -- data_tys will simply be the dataConUnivTyVars
+ -- NB: A newtype always has a vanilla DataCon; no existentials etc
+ -- data_tys will simply be the dataConUnivTyVars
sel_body | isNewTyCon tycon = unwrapNewTypeBody tycon scrut_ty_args scrut
- | otherwise = Case scrut scrut_id field_ty (default_alt ++ the_alts)
+ | otherwise = Case scrut scrut_id field_ty (default_alt ++ the_alts)
mk_result poly_result = mkVarApps (mkVarApps poly_result field_tyvars) field_dict_ids
- -- We pull the field lambdas to the top, so we need to
- -- apply them in the body. For example:
- -- data T = MkT { foo :: forall a. a->a }
- --
- -- foo :: forall a. T -> a -> a
- -- foo = /\a. \t:T. case t of { MkT f -> f a }
-
- mk_alt data_con
- = ASSERT2( data_ty `tcEqType` field_ty, ppr data_con $$ ppr data_ty $$ ppr field_ty )
- mkReboxingAlt rebox_uniqs data_con (ex_tvs ++ co_tvs ++ arg_vs) rhs
+ -- We pull the field lambdas to the top, so we need to
+ -- apply them in the body. For example:
+ -- data T = MkT { foo :: forall a. a->a }
+ --
+ -- foo :: forall a. T -> a -> a
+ -- foo = /\a. \t:T. case t of { MkT f -> f a }
+
+ mk_alt data_con
+ = ASSERT2( data_ty `tcEqType` field_ty,
+ ppr data_con $$ ppr data_ty $$ ppr field_ty )
+ mkReboxingAlt rebox_uniqs data_con (ex_tvs ++ co_tvs ++ arg_vs) rhs
where
-- get pattern binders with types appropriately instantiated
- arg_uniqs = map mkBuiltinUnique [arg_base..]
- (ex_tvs, co_tvs, arg_vs) = dataConOrigInstPat arg_uniqs data_con scrut_ty_args
-
- rebox_base = arg_base + length ex_tvs + length co_tvs + length arg_vs
- rebox_uniqs = map mkBuiltinUnique [rebox_base..]
-
- -- data T :: *->* where T1 { fld :: Maybe b } -> T [b]
- -- Hence T1 :: forall a b. (a=[b]) => b -> T a
- -- fld :: forall b. T [b] -> Maybe b
- -- fld = /\b.\(t:T[b]). case t of
- -- T1 b' (c : [b]=[b']) (x:Maybe b')
- -- -> x `cast` Maybe (sym (right c))
-
-
- -- Generate the refinement for b'=b,
- -- and apply to (Maybe b'), to get (Maybe b)
- Succeeded refinement = gadtRefine emptyRefinement ex_tvs co_tvs
- the_arg_id_ty = idType the_arg_id
- (rhs, data_ty) = case refineType refinement the_arg_id_ty of
- Just (co, data_ty) -> (Cast (Var the_arg_id) co, data_ty)
- Nothing -> (Var the_arg_id, the_arg_id_ty)
-
- field_vs = filter (not . isPredTy . idType) arg_vs
- the_arg_id = assoc "mkRecordSelId:mk_alt" (field_lbls `zip` field_vs) field_label
- field_lbls = dataConFieldLabels data_con
+ arg_uniqs = map mkBuiltinUnique [arg_base..]
+ (ex_tvs, co_tvs, arg_vs) = dataConOrigInstPat arg_uniqs data_con
+ scrut_ty_args
+
+ rebox_base = arg_base + length ex_tvs + length co_tvs + length arg_vs
+ rebox_uniqs = map mkBuiltinUnique [rebox_base..]
+
+ -- data T :: *->* where T1 { fld :: Maybe b } -> T [b]
+ -- Hence T1 :: forall a b. (a=[b]) => b -> T a
+ -- fld :: forall b. T [b] -> Maybe b
+ -- fld = /\b.\(t:T[b]). case t of
+ -- T1 b' (c : [b]=[b']) (x:Maybe b')
+ -- -> x `cast` Maybe (sym (right c))
+
+ -- Generate the refinement for b'=b,
+ -- and apply to (Maybe b'), to get (Maybe b)
+ reft = matchRefine co_tvs
+ the_arg_id_ty = idType the_arg_id
+ (rhs, data_ty) =
+ case refineType reft the_arg_id_ty of
+ Just (co, data_ty) -> (Cast (Var the_arg_id) co, data_ty)
+ Nothing -> (Var the_arg_id, the_arg_id_ty)
+
+ field_vs = filter (not . isPredTy . idType) arg_vs
+ the_arg_id = assoc "mkRecordSelId:mk_alt"
+ (field_lbls `zip` field_vs) field_label
+ field_lbls = dataConFieldLabels data_con
error_expr = mkRuntimeErrorApp rEC_SEL_ERROR_ID field_ty full_msg
full_msg = showSDoc (sep [text "No match in record selector", ppr sel_id])
mkUnpackCase :: Id -> CoreExpr -> [Id] -> DataCon -> CoreExpr -> CoreExpr
-- (mkUnpackCase x e args Con body)
--- returns
+-- returns
-- case (e `cast` ...) of bndr { Con args -> body }
--
-- the type of the bndr passed in is irrelevent
[Id]) -- Ids being boxed into product
reboxProduct us ty
= let
- (_tycon, _tycon_args, _pack_con, con_arg_tys) = deepSplitProductType "reboxProduct" ty
+ (_tycon, _tycon_args, _pack_con, con_arg_tys) = deepSplitProductType "reboxProduct" ty
us' = dropList con_arg_tys us
- arg_ids = zipWith (mkSysLocal FSLIT("rb")) us con_arg_tys
+ arg_ids = zipWith (mkSysLocal (fsLit "rb")) us con_arg_tys
bind_rhs = mkProductBox arg_ids ty
-- (mkReboxingAlt us con xs rhs) basically constructs the case
--- alternative (con, xs, rhs)
+-- alternative (con, xs, rhs)
-- but it does the reboxing necessary to construct the *source*
-- arguments, xs, from the representation arguments ys.
-- For example:
--- data T = MkT !(Int,Int) Bool
+-- data T = MkT !(Int,Int) Bool
--
-- mkReboxingAlt MkT [x,b] r
--- = (DataAlt MkT, [y::Int,z::Int,b], let x = (y,z) in r)
+-- = (DataAlt MkT, [y::Int,z::Int,b], let x = (y,z) in r)
--
-- mkDataAlt should really be in DataCon, but it can't because
-- it manipulates CoreSyn.
mkReboxingAlt
- :: [Unique] -- Uniques for the new Ids
+ :: [Unique] -- Uniques for the new Ids
-> DataCon
- -> [Var] -- Source-level args, including existential dicts
- -> CoreExpr -- RHS
+ -> [Var] -- Source-level args, including existential dicts
+ -> CoreExpr -- RHS
-> CoreAlt
mkReboxingAlt us con args rhs
| otherwise
= let
- (binds, args') = go args stricts us
+ (binds, args') = go args stricts us
in
(DataAlt con, args', mkLets binds rhs)
go [] _stricts _us = ([], [])
- -- Type variable case
+ -- Type variable case
go (arg:args) stricts us
| isTyVar arg
= let (binds, args') = go args stricts us
- in (binds, arg:args')
+ in (binds, arg:args')
- -- Term variable case
+ -- Term variable case
go (arg:args) (str:stricts) us
| isMarkedUnboxed str
=
| otherwise
= let (binds, args') = go args stricts us
in (binds, arg:args')
+ go (_ : _) [] _ = panic "mkReboxingAlt"
\end{code}
%************************************************************************
-%* *
+%* *
\subsection{Dictionary selectors}
-%* *
+%* *
%************************************************************************
Selecting a field for a dictionary. If there is just one field, then
Dictionary selectors may get nested forall-types. Thus:
- class Foo a where
- op :: forall b. Ord b => a -> b -> b
+ class Foo a where
+ op :: forall b. Ord b => a -> b -> b
Then the top-level type for op is
- op :: forall a. Foo a =>
- forall b. Ord b =>
- a -> b -> b
+ op :: forall a. Foo a =>
+ forall b. Ord b =>
+ a -> b -> b
This is unlike ordinary record selectors, which have all the for-alls
at the outside. When dealing with classes it's very convenient to
recover the original type signature from the class op selector.
\begin{code}
-mkDictSelId :: Name -> Class -> Id
-mkDictSelId name clas
+mkDictSelId :: Bool -- True <=> don't include the unfolding
+ -- Little point on imports without -O, because the
+ -- dictionary itself won't be visible
+ -> Name -> Class -> Id
+mkDictSelId no_unf name clas
= mkGlobalId (ClassOpId clas) name sel_ty info
where
sel_ty = mkForAllTys tyvars (mkFunTy (idType dict_id) (idType the_arg_id))
- -- We can't just say (exprType rhs), because that would give a type
- -- C a -> C a
- -- for a single-op class (after all, the selector is the identity)
- -- But it's type must expose the representation of the dictionary
- -- to get (say) C a -> (a -> a)
+ -- We can't just say (exprType rhs), because that would give a type
+ -- C a -> C a
+ -- for a single-op class (after all, the selector is the identity)
+ -- But it's type must expose the representation of the dictionary
+ -- to get (say) C a -> (a -> a)
info = noCafIdInfo
- `setArityInfo` 1
- `setUnfoldingInfo` mkTopUnfolding rhs
- `setAllStrictnessInfo` Just strict_sig
-
- -- We no longer use 'must-inline' on record selectors. They'll
- -- inline like crazy if they scrutinise a constructor
-
- -- The strictness signature is of the form U(AAAVAAAA) -> T
- -- where the V depends on which item we are selecting
- -- It's worth giving one, so that absence info etc is generated
- -- even if the selector isn't inlined
+ `setArityInfo` 1
+ `setAllStrictnessInfo` Just strict_sig
+ `setUnfoldingInfo` (if no_unf then noUnfolding
+ else mkTopUnfolding rhs)
+
+ -- We no longer use 'must-inline' on record selectors. They'll
+ -- inline like crazy if they scrutinise a constructor
+
+ -- The strictness signature is of the form U(AAAVAAAA) -> T
+ -- where the V depends on which item we are selecting
+ -- It's worth giving one, so that absence info etc is generated
+ -- even if the selector isn't inlined
strict_sig = mkStrictSig (mkTopDmdType [arg_dmd] TopRes)
arg_dmd | isNewTyCon tycon = evalDmd
- | otherwise = Eval (Prod [ if the_arg_id == id then evalDmd else Abs
- | id <- arg_ids ])
+ | otherwise = Eval (Prod [ if the_arg_id == id then evalDmd else Abs
+ | id <- arg_ids ])
tycon = classTyCon clas
[data_con] = tyConDataCons tycon
tyvars = dataConUnivTyVars data_con
arg_tys = {- ASSERT( isVanillaDataCon data_con ) -} dataConRepArgTys data_con
- eq_theta = dataConEqTheta data_con
+ eq_theta = dataConEqTheta data_con
the_arg_id = assoc "MkId.mkDictSelId" (map idName (classSelIds clas) `zip` arg_ids) name
pred = mkClassPred clas (mkTyVarTys tyvars)
mkCoVarLocals i [] = ([],i)
mkCoVarLocals i (x:xs) = let (ys,j) = mkCoVarLocals (i+1) xs
- y = mkCoVar (mkSysTvName (mkBuiltinUnique i) FSLIT("dc_co")) x
+ y = mkCoVar (mkSysTvName (mkBuiltinUnique i) (fsLit "dc_co")) x
in (y:ys,j)
rhs = mkLams tyvars (Lam dict_id rhs_body)
rhs_body | isNewTyCon tycon = unwrapNewTypeBody tycon (map mkTyVarTy tyvars) (Var dict_id)
- | otherwise = Case (Var dict_id) dict_id (idType the_arg_id)
- [(DataAlt data_con, eq_ids ++ arg_ids, Var the_arg_id)]
+ | otherwise = Case (Var dict_id) dict_id (idType the_arg_id)
+ [(DataAlt data_con, eq_ids ++ arg_ids, Var the_arg_id)]
\end{code}
%************************************************************************
-%* *
- Wrapping and unwrapping newtypes and type families
-%* *
+%* *
+ Wrapping and unwrapping newtypes and type families
+%* *
%************************************************************************
\begin{code}
wrapNewTypeBody :: TyCon -> [Type] -> CoreExpr -> CoreExpr
-- The wrapper for the data constructor for a newtype looks like this:
--- newtype T a = MkT (a,Int)
--- MkT :: forall a. (a,Int) -> T a
--- MkT = /\a. \(x:(a,Int)). x `cast` sym (CoT a)
+-- newtype T a = MkT (a,Int)
+-- MkT :: forall a. (a,Int) -> T a
+-- MkT = /\a. \(x:(a,Int)). x `cast` sym (CoT a)
-- where CoT is the coercion TyCon assoicated with the newtype
--
-- The call (wrapNewTypeBody T [a] e) returns the
-- body of the wrapper, namely
--- e `cast` (CoT [a])
+-- e `cast` (CoT [a])
--
-- If a coercion constructor is provided in the newtype, then we use
-- it, otherwise the wrap/unwrap are both no-ops
%************************************************************************
-%* *
+%* *
\subsection{Primitive operations
-%* *
+%* *
%************************************************************************
\begin{code}
(tyvars,arg_tys,res_ty, arity, strict_sig) = primOpSig prim_op
ty = mkForAllTys tyvars (mkFunTys arg_tys res_ty)
name = mkWiredInName gHC_PRIM (primOpOcc prim_op)
- (mkPrimOpIdUnique (primOpTag prim_op))
- (AnId id) UserSyntax
+ (mkPrimOpIdUnique (primOpTag prim_op))
+ (AnId id) UserSyntax
id = mkGlobalId (PrimOpId prim_op) name ty info
-
+
info = noCafIdInfo
- `setSpecInfo` mkSpecInfo (primOpRules prim_op name)
- `setArityInfo` arity
- `setAllStrictnessInfo` Just strict_sig
+ `setSpecInfo` mkSpecInfo (primOpRules prim_op name)
+ `setArityInfo` arity
+ `setAllStrictnessInfo` Just strict_sig
-- For each ccall we manufacture a separate CCallOpId, giving it
-- a fresh unique, a type that is correct for this particular ccall,
mkFCallId :: Unique -> ForeignCall -> Type -> Id
mkFCallId uniq fcall ty
= ASSERT( isEmptyVarSet (tyVarsOfType ty) )
- -- A CCallOpId should have no free type variables;
- -- when doing substitutions won't substitute over it
+ -- A CCallOpId should have no free type variables;
+ -- when doing substitutions won't substitute over it
mkGlobalId (FCallId fcall) name ty info
where
occ_str = showSDoc (braces (ppr fcall <+> ppr ty))
- -- The "occurrence name" of a ccall is the full info about the
- -- ccall; it is encoded, but may have embedded spaces etc!
+ -- The "occurrence name" of a ccall is the full info about the
+ -- ccall; it is encoded, but may have embedded spaces etc!
name = mkFCallName uniq occ_str
info = noCafIdInfo
- `setArityInfo` arity
- `setAllStrictnessInfo` Just strict_sig
+ `setArityInfo` arity
+ `setAllStrictnessInfo` Just strict_sig
- (_, tau) = tcSplitForAllTys ty
+ (_, tau) = tcSplitForAllTys ty
(arg_tys, _) = tcSplitFunTys tau
- arity = length arg_tys
+ arity = length arg_tys
strict_sig = mkStrictSig (mkTopDmdType (replicate arity evalDmd) TopRes)
-- Tick boxes and breakpoints are both represented as TickBoxOpIds,
%************************************************************************
-%* *
+%* *
\subsection{DictFuns and default methods}
-%* *
+%* *
%************************************************************************
Important notes about dict funs and default methods
\begin{code}
mkDefaultMethodId dm_name ty = mkExportedLocalId dm_name ty
-mkDictFunId :: Name -- Name to use for the dict fun;
- -> [TyVar]
- -> ThetaType
- -> Class
- -> [Type]
- -> Id
+mkDictFunId :: Name -- Name to use for the dict fun;
+ -> [TyVar]
+ -> ThetaType
+ -> Class
+ -> [Type]
+ -> Id
mkDictFunId dfun_name inst_tyvars dfun_theta clas inst_tys
= mkExportedLocalId dfun_name dfun_ty
not_const (clas, tys) = not (isEmptyVarSet (tyVarsOfTypes tys))
sc_theta' = substClasses (zipTopTvSubst class_tyvars inst_tys) sc_theta
dfun_theta = case inst_decl_theta of
- [] -> [] -- If inst_decl_theta is empty, then we don't
- -- want to have any dict arguments, so that we can
- -- expose the constant methods.
-
- other -> nub (inst_decl_theta ++ filter not_const sc_theta')
- -- Otherwise we pass the superclass dictionaries to
- -- the dictionary function; the Mark Jones optimisation.
- --
- -- NOTE the "nub". I got caught by this one:
- -- class Monad m => MonadT t m where ...
- -- instance Monad m => MonadT (EnvT env) m where ...
- -- Here, the inst_decl_theta has (Monad m); but so
- -- does the sc_theta'!
- --
- -- NOTE the "not_const". I got caught by this one too:
- -- class Foo a => Baz a b where ...
- -- instance Wob b => Baz T b where..
- -- Now sc_theta' has Foo T
+ [] -> [] -- If inst_decl_theta is empty, then we don't
+ -- want to have any dict arguments, so that we can
+ -- expose the constant methods.
+
+ other -> nub (inst_decl_theta ++ filter not_const sc_theta')
+ -- Otherwise we pass the superclass dictionaries to
+ -- the dictionary function; the Mark Jones optimisation.
+ --
+ -- NOTE the "nub". I got caught by this one:
+ -- class Monad m => MonadT t m where ...
+ -- instance Monad m => MonadT (EnvT env) m where ...
+ -- Here, the inst_decl_theta has (Monad m); but so
+ -- does the sc_theta'!
+ --
+ -- NOTE the "not_const". I got caught by this one too:
+ -- class Foo a => Baz a b where ...
+ -- instance Wob b => Baz T b where..
+ -- Now sc_theta' has Foo T
-}
\end{code}
%************************************************************************
-%* *
+%* *
\subsection{Un-definable}
-%* *
+%* *
%************************************************************************
These Ids can't be defined in Haskell. They could be defined in
mkWiredInIdName mod fs uniq id
= mkWiredInName mod (mkOccNameFS varName fs) uniq (AnId id) UserSyntax
-unsafeCoerceName = mkWiredInIdName gHC_PRIM FSLIT("unsafeCoerce#") unsafeCoerceIdKey unsafeCoerceId
-nullAddrName = mkWiredInIdName gHC_PRIM FSLIT("nullAddr#") nullAddrIdKey nullAddrId
-seqName = mkWiredInIdName gHC_PRIM FSLIT("seq") seqIdKey seqId
-realWorldName = mkWiredInIdName gHC_PRIM FSLIT("realWorld#") realWorldPrimIdKey realWorldPrimId
-lazyIdName = mkWiredInIdName gHC_BASE FSLIT("lazy") lazyIdKey lazyId
-
-errorName = mkWiredInIdName gHC_ERR FSLIT("error") errorIdKey eRROR_ID
-recSelErrorName = mkWiredInIdName gHC_ERR FSLIT("recSelError") recSelErrorIdKey rEC_SEL_ERROR_ID
-runtimeErrorName = mkWiredInIdName gHC_ERR FSLIT("runtimeError") runtimeErrorIdKey rUNTIME_ERROR_ID
-irrefutPatErrorName = mkWiredInIdName gHC_ERR FSLIT("irrefutPatError") irrefutPatErrorIdKey iRREFUT_PAT_ERROR_ID
-recConErrorName = mkWiredInIdName gHC_ERR FSLIT("recConError") recConErrorIdKey rEC_CON_ERROR_ID
-patErrorName = mkWiredInIdName gHC_ERR FSLIT("patError") patErrorIdKey pAT_ERROR_ID
-noMethodBindingErrorName = mkWiredInIdName gHC_ERR FSLIT("noMethodBindingError")
- noMethodBindingErrorIdKey nO_METHOD_BINDING_ERROR_ID
+unsafeCoerceName = mkWiredInIdName gHC_PRIM (fsLit "unsafeCoerce#") unsafeCoerceIdKey unsafeCoerceId
+nullAddrName = mkWiredInIdName gHC_PRIM (fsLit "nullAddr#") nullAddrIdKey nullAddrId
+seqName = mkWiredInIdName gHC_PRIM (fsLit "seq") seqIdKey seqId
+realWorldName = mkWiredInIdName gHC_PRIM (fsLit "realWorld#") realWorldPrimIdKey realWorldPrimId
+lazyIdName = mkWiredInIdName gHC_BASE (fsLit "lazy") lazyIdKey lazyId
+
+errorName = mkWiredInIdName gHC_ERR (fsLit "error") errorIdKey eRROR_ID
+recSelErrorName = mkWiredInIdName gHC_ERR (fsLit "recSelError") recSelErrorIdKey rEC_SEL_ERROR_ID
+runtimeErrorName = mkWiredInIdName gHC_ERR (fsLit "runtimeError") runtimeErrorIdKey rUNTIME_ERROR_ID
+irrefutPatErrorName = mkWiredInIdName gHC_ERR (fsLit "irrefutPatError") irrefutPatErrorIdKey iRREFUT_PAT_ERROR_ID
+recConErrorName = mkWiredInIdName gHC_ERR (fsLit "recConError") recConErrorIdKey rEC_CON_ERROR_ID
+patErrorName = mkWiredInIdName gHC_ERR (fsLit "patError") patErrorIdKey pAT_ERROR_ID
+noMethodBindingErrorName = mkWiredInIdName gHC_ERR (fsLit "noMethodBindingError")
+ noMethodBindingErrorIdKey nO_METHOD_BINDING_ERROR_ID
nonExhaustiveGuardsErrorName
- = mkWiredInIdName gHC_ERR FSLIT("nonExhaustiveGuardsError")
- nonExhaustiveGuardsErrorIdKey nON_EXHAUSTIVE_GUARDS_ERROR_ID
+ = mkWiredInIdName gHC_ERR (fsLit "nonExhaustiveGuardsError")
+ nonExhaustiveGuardsErrorIdKey nON_EXHAUSTIVE_GUARDS_ERROR_ID
\end{code}
\begin{code}
+------------------------------------------------
-- unsafeCoerce# :: forall a b. a -> b
unsafeCoerceId
= pcMiscPrelId unsafeCoerceName ty info
where
info = noCafIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
-
+
ty = mkForAllTys [openAlphaTyVar,openBetaTyVar]
- (mkFunTy openAlphaTy openBetaTy)
+ (mkFunTy openAlphaTy openBetaTy)
[x] = mkTemplateLocals [openAlphaTy]
rhs = mkLams [openAlphaTyVar,openBetaTyVar,x] $
Cast (Var x) (mkUnsafeCoercion openAlphaTy openBetaTy)
+------------------------------------------------
+nullAddrId :: Id
-- nullAddr# :: Addr#
-- The reason is is here is because we don't provide
-- a way to write this literal in Haskell.
-nullAddrId
- = pcMiscPrelId nullAddrName addrPrimTy info
+nullAddrId = pcMiscPrelId nullAddrName addrPrimTy info
where
info = noCafIdInfo `setUnfoldingInfo`
- mkCompulsoryUnfolding (Lit nullAddrLit)
-
-seqId
- = pcMiscPrelId seqName ty info
+ mkCompulsoryUnfolding (Lit nullAddrLit)
+
+------------------------------------------------
+seqId :: Id
+-- 'seq' is very special. See notes with
+-- See DsUtils.lhs Note [Desugaring seq (1)] and
+-- Note [Desugaring seq (2)] and
+-- Fixity is set in LoadIface.ghcPrimIface
+seqId = pcMiscPrelId seqName ty info
where
info = noCafIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
-
+
ty = mkForAllTys [alphaTyVar,openBetaTyVar]
- (mkFunTy alphaTy (mkFunTy openBetaTy openBetaTy))
+ (mkFunTy alphaTy (mkFunTy openBetaTy openBetaTy))
[x,y] = mkTemplateLocals [alphaTy, openBetaTy]
rhs = mkLams [alphaTyVar,openBetaTyVar,x,y] (Case (Var x) x openBetaTy [(DEFAULT, [], Var y)])
--- lazy :: forall a?. a? -> a? (i.e. works for unboxed types too)
--- Used to lazify pseq: pseq a b = a `seq` lazy b
+------------------------------------------------
+lazyId :: Id
+-- lazy :: forall a?. a? -> a? (i.e. works for unboxed types too)
+-- Used to lazify pseq: pseq a b = a `seq` lazy b
--
-- Also, no strictness: by being a built-in Id, all the info about lazyId comes from here,
-- not from GHC.Base.hi. This is important, because the strictness
-- analyser will spot it as strict!
--
-- Also no unfolding in lazyId: it gets "inlined" by a HACK in the worker/wrapperpass
--- (see WorkWrap.wwExpr)
+-- (see WorkWrap.wwExpr)
-- We could use inline phases to do this, but that would be vulnerable to changes in
-- phase numbering....we must inline precisely after strictness analysis.
-lazyId
- = pcMiscPrelId lazyIdName ty info
+lazyId = pcMiscPrelId lazyIdName ty info
where
info = noCafIdInfo
ty = mkForAllTys [alphaTyVar] (mkFunTy alphaTy alphaTy)
-lazyIdUnfolding :: CoreExpr -- Used to expand 'lazyId' after strictness anal
+lazyIdUnfolding :: CoreExpr -- Used to expand 'lazyId' after strictness anal
lazyIdUnfolding = mkLams [openAlphaTyVar,x] (Var x)
- where
- [x] = mkTemplateLocals [openAlphaTy]
+ where
+ [x] = mkTemplateLocals [openAlphaTy]
\end{code}
@realWorld#@ used to be a magic literal, \tr{void#}. If things get
voidArgId is a Local Id used simply as an argument in functions
where we just want an arg to avoid having a thunk of unlifted type.
E.g.
- x = \ void :: State# RealWorld -> (# p, q #)
+ x = \ void :: State# RealWorld -> (# p, q #)
This comes up in strictness analysis
\begin{code}
-realWorldPrimId -- :: State# RealWorld
+realWorldPrimId -- :: State# RealWorld
= pcMiscPrelId realWorldName realWorldStatePrimTy
- (noCafIdInfo `setUnfoldingInfo` evaldUnfolding)
- -- The evaldUnfolding makes it look that realWorld# is evaluated
- -- which in turn makes Simplify.interestingArg return True,
- -- which in turn makes INLINE things applied to realWorld# likely
- -- to be inlined
-
-voidArgId -- :: State# RealWorld
- = mkSysLocal FSLIT("void") voidArgIdKey realWorldStatePrimTy
+ (noCafIdInfo `setUnfoldingInfo` evaldUnfolding)
+ -- The evaldUnfolding makes it look that realWorld# is evaluated
+ -- which in turn makes Simplify.interestingArg return True,
+ -- which in turn makes INLINE things applied to realWorld# likely
+ -- to be inlined
+
+voidArgId :: Id
+voidArgId -- :: State# RealWorld
+ = mkSysLocal (fsLit "void") voidArgIdKey realWorldStatePrimTy
\end{code}
%************************************************************************
-%* *
+%* *
\subsection[PrelVals-error-related]{@error@ and friends; @trace@}
-%* *
+%* *
%************************************************************************
GHC randomly injects these into the code.
\begin{code}
mkRuntimeErrorApp
- :: Id -- Should be of type (forall a. Addr# -> a)
- -- where Addr# points to a UTF8 encoded string
- -> Type -- The type to instantiate 'a'
- -> String -- The string to print
- -> CoreExpr
+ :: Id -- Should be of type (forall a. Addr# -> a)
+ -- where Addr# points to a UTF8 encoded string
+ -> Type -- The type to instantiate 'a'
+ -> String -- The string to print
+ -> CoreExpr
mkRuntimeErrorApp err_id res_ty err_msg
= mkApps (Var err_id) [Type res_ty, err_string]
where
err_string = Lit (mkStringLit err_msg)
-rEC_SEL_ERROR_ID = mkRuntimeErrorId recSelErrorName
-rUNTIME_ERROR_ID = mkRuntimeErrorId runtimeErrorName
-iRREFUT_PAT_ERROR_ID = mkRuntimeErrorId irrefutPatErrorName
-rEC_CON_ERROR_ID = mkRuntimeErrorId recConErrorName
-pAT_ERROR_ID = mkRuntimeErrorId patErrorName
+rEC_SEL_ERROR_ID = mkRuntimeErrorId recSelErrorName
+rUNTIME_ERROR_ID = mkRuntimeErrorId runtimeErrorName
+iRREFUT_PAT_ERROR_ID = mkRuntimeErrorId irrefutPatErrorName
+rEC_CON_ERROR_ID = mkRuntimeErrorId recConErrorName
+pAT_ERROR_ID = mkRuntimeErrorId patErrorName
nO_METHOD_BINDING_ERROR_ID = mkRuntimeErrorId noMethodBindingErrorName
-nON_EXHAUSTIVE_GUARDS_ERROR_ID = mkRuntimeErrorId nonExhaustiveGuardsErrorName
+nON_EXHAUSTIVE_GUARDS_ERROR_ID = mkRuntimeErrorId nonExhaustiveGuardsErrorName
-- The runtime error Ids take a UTF8-encoded string as argument
+
+mkRuntimeErrorId :: Name -> Id
mkRuntimeErrorId name = pc_bottoming_Id name runtimeErrorTy
-runtimeErrorTy = mkSigmaTy [openAlphaTyVar] [] (mkFunTy addrPrimTy openAlphaTy)
+
+runtimeErrorTy :: Type
+runtimeErrorTy = mkSigmaTy [openAlphaTyVar] [] (mkFunTy addrPrimTy openAlphaTy)
\end{code}
\begin{code}
%************************************************************************
-%* *
+%* *
\subsection{Utilities}
-%* *
+%* *
%************************************************************************
\begin{code}
-- being compiled, then it's just a matter of luck if the definition
-- will be in "the right place" to be in scope.
+pc_bottoming_Id :: Name -> Type -> Id
+-- Function of arity 1, which diverges after being given one argument
pc_bottoming_Id name ty
= pcMiscPrelId name ty bottoming_info
where
bottoming_info = vanillaIdInfo `setAllStrictnessInfo` Just strict_sig
- -- Do *not* mark them as NoCafRefs, because they can indeed have
- -- CAF refs. For example, pAT_ERROR_ID calls GHC.Err.untangle,
- -- which has some CAFs
- -- In due course we may arrange that these error-y things are
- -- regarded by the GC as permanently live, in which case we
- -- can give them NoCaf info. As it is, any function that calls
- -- any pc_bottoming_Id will itself have CafRefs, which bloats
- -- SRTs.
-
- strict_sig = mkStrictSig (mkTopDmdType [evalDmd] BotRes)
- -- These "bottom" out, no matter what their arguments
+ `setArityInfo` 1
+ -- Make arity and strictness agree
+
+ -- Do *not* mark them as NoCafRefs, because they can indeed have
+ -- CAF refs. For example, pAT_ERROR_ID calls GHC.Err.untangle,
+ -- which has some CAFs
+ -- In due course we may arrange that these error-y things are
+ -- regarded by the GC as permanently live, in which case we
+ -- can give them NoCaf info. As it is, any function that calls
+ -- any pc_bottoming_Id will itself have CafRefs, which bloats
+ -- SRTs.
+
+ strict_sig = mkStrictSig (mkTopDmdType [evalDmd] BotRes)
+ -- These "bottom" out, no matter what their arguments
\end{code}