
OK, so one thing I failed to explain in the comment is this: for imported DataCons, the dcSrcBangs field is precisely the [HsImplBang] decisions computed when compiling the defining module.
So if the defining module was compiled with –O –funbox-strict-fields, GHC will make one set of choices. Those [HsImplBang] choices are recorded in the IfaceBangs in the interface file. Those IfaceBangs in turn get put back into the dcSrcBangs field of the DataCon constructed by TcIface when reading the interface file.
So when the dcSrcBangs are in fact HsImpBangs, they should be followed slavishly, because the decisions have already been taken. Even if the –O or –funbox-strict-fields flags differ in the importing module from the defining module.
I’ve rewritten the comment below.
Maybe the field should not be called dcSrcBangs but dcOrigBangs?
Simon
{- Note [Bangs on data constructor arguments]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider
data T = MkT !Int {-# UNPACK #-} !Int Bool
When compiling the module, GHC will decide how to represent
MkT, depending on the optimisation level, and settings of
flags like -funbox-small-strict-fields.
Terminology:
* HsSrcBang: What the user wrote
Constructors: HsNoBang, HsUserBang
* HsImplBang: What GHC decided
Constructors: HsNoBang, HsStrict, HsUnpack
* If T was defined in this module, MkT's dcSrcBangs field
records the [HsSrcBang] of what the user wrote; in the example
[ HsSrcBang Nothing True
, HsSrcBang (Just True) True
, HsNoBang]
* However, if T was defined in an imported module, MkT's dcSrcBangs
field gives the [HsImplBang] recording the decisions of the
defining module. The importing module must follow those decisions,
regardless of the flag settings in the importing module.
* The dcr_bangs field of the dcRep field records the [HsImplBang]
If T was defined in this module, Without -O the dcr_bangs might be
[HsStrict, HsStrict, HsNoBang]
With -O it might be
[HsStrict, HsUnpack, HsNoBang]
With -funbox-small-strict-fields it might be
[HsUnpack, HsUnpack, HsNoBang]
From: Johan Tibell [mailto:johan.tibell@gmail.com]
Sent: 11 January 2015 17:28
To: Simon Peyton Jones
Cc: ghc-devs@haskell.org
Subject: Re: Clarification of HsBang and isBanged
Those comments and the renaming really help. Here are a couple of more questions I got after exploring some more:
DsMeta.repBangTy look wrong to me:
repBangTy :: LBangType Name -> DsM (Core (TH.StrictTypeQ))
repBangTy ty= do
MkC s <- rep2 str []
MkC t <- repLTy ty'
rep2 strictTypeName [s, t]
where
(str, ty') = case ty of
L _ (HsBangTy (HsSrcBang (Just True) True) ty) -> (unpackedName, ty)
L _ (HsBangTy (HsSrcBang _ True) ty) -> (isStrictName, ty)
_ -> (notStrictName, ty)
Shouldn't the second case look at whether -funbox-strict-fields or -funbox-small-strict-fields is set and use unpackedName instead of isStrictName if so? What is repBangTy for?
A related question, in MkId.dataConArgRep we have:
dataConArgRep _ _ arg_ty HsStrict
= strict_but_not_unpacked arg_ty
Here we're not looking at -funbox-strict-fields and -funbox-small-strict-fields. Is it the case that we only need to look at these flags in the case of HsSrcBang, because HsStrict can only be generated by us (and we presumably looked at the flags when we converted a HsSrcBang to a HsStrict)?
On Thu, Jan 8, 2015 at 4:09 PM, Simon Peyton Jones