More comments on HsBang
authorSimon Peyton Jones <simonpj@microsoft.com>
Sun, 11 Jan 2015 23:07:24 +0000 (23:07 +0000)
committerSimon Peyton Jones <simonpj@microsoft.com>
Sun, 11 Jan 2015 23:08:04 +0000 (23:08 +0000)
In particular about the dcSrcBangs field of an imported DataCon

compiler/basicTypes/DataCon.hs
compiler/basicTypes/MkId.hs
compiler/iface/BuildTyCl.hs
compiler/iface/IfaceSyn.hs
compiler/iface/TcIface.hs

index 3f27acd..593e0ed 100644 (file)
@@ -343,9 +343,14 @@ data DataCon
                 -- The OrigResTy is T [a], but the dcRepTyCon might be :T123
 
         -- Now the strictness annotations and field labels of the constructor
-        -- See Note [Bangs on data constructor arguments]
-        dcSrcBangs :: [HsSrcBang],
-                -- Strictness annotations as written by the programmer.
+        dcSrcBangs :: [HsBang],
+                -- See Note [Bangs on data constructor arguments]
+                -- For DataCons defined in this module: 
+                --    the [HsSrcBang] as written by the programmer.
+                -- For DataCons imported from an interface file:
+                --    the [HsImplBang] determined when compiling the
+                --    defining module
+                -- 
                 -- Matches 1-1 with dcOrigArgTys
                 -- Hence length = dataConSourceArity dataCon
 
@@ -466,7 +471,6 @@ data HsBang
 
 -- Two type-insecure, but useful, synonyms
 type HsSrcBang = HsBang   -- What the user wrote; hence always HsNoBang or HsSrcBang
-                          -- But see Note [HsSrcBang exceptions]
 
 type HsImplBang = HsBang   -- A HsBang implementation decision,
                            -- as determined by the compiler
@@ -477,16 +481,40 @@ type HsImplBang = HsBang   -- A HsBang implementation decision,
 -- of the DataCon *worker* fields
 data StrictnessMark = MarkedStrict | NotMarkedStrict
 
-{- Note [HsSrcBang exceptions]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Exceptions to rule that HsSrcBang is always HsSrcBang or HsNoBang:
+{- 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
 
-* When we build a DataCon from an interface file we don't
-  know what the user wrote, so we use HsUnpack/HsStrict
+* 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]
 
-* In MkId.mkDataConRep we want to say "always unpack an equality
-  predicate for equality arguments so we use HsUnpack
-  see MkId.mk_pred_strict_mark
+* 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]
 
 Note [Data con representation]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -506,25 +534,6 @@ but the rep type is
         Trep :: Int# -> a -> T a
 Actually, the unboxed part isn't implemented yet!
 
-Note [Bangs on data constructor arguments]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Consider
-  data T = MkT !Int {-# UNPACK #-} !Int Bool
-Its dcSrcBangs field records the *users* specifications, in this case
-    [ HsSrcBang Nothing True
-    , HsSrcBang (Just True) True
-    , HsNoBang]
-
-The dcr_bangs field of the dcRep field records the *actual, decided*
-representation of the data constructor.  Without -O this might be
-    [HsStrict, HsStrict, HsNoBang]
-With -O it might be
-    [HsStrict, HsUnpack, HsNoBang]
-With -funbox-small-strict-fields it might be
-    [HsUnpack, HsUnpack, HsNoBang]
-
-For imported data types, the dcSrcBangs field is just the same as the
-dcr_bangs field; we don't know what the user originally said.
 
 
 ************************************************************************
@@ -610,7 +619,8 @@ isMarkedStrict _               = True   -- All others are strict
 -- | Build a new data constructor
 mkDataCon :: Name
           -> Bool               -- ^ Is the constructor declared infix?
-          -> [HsSrcBang]        -- ^ User-supplied strictness/unpack annotations
+          -> [HsBang]           -- ^ Strictness/unpack annotations, from user, of
+                                --   (for imported DataCons) from the interface file 
           -> [FieldLabel]       -- ^ Field labels for the constructor, if it is a record,
                                 --   otherwise empty
           -> [TyVar]            -- ^ Universally quantified type variables
index 0899997..7f24faa 100644 (file)
@@ -580,7 +580,14 @@ newLocal ty = do { uniq <- getUniqueM
 dataConArgRep
    :: DynFlags
    -> FamInstEnvs
-   -> Type -> HsSrcBang
+   -> Type 
+   -> HsSrcBang     -- For DataCons defined in this module, this is the
+                    --    bang/unpack annotation that the programmer wrote
+                    -- For DataCons imported from an interface file, this
+                    --    is the HsImplBang implementation decision taken
+                    --    by the compiler in the defining module; just follow
+                    --    it slavishly, so that we make the same decision as
+                    --    in the defining module
    -> ( HsImplBang                 -- Implementation decision about unpack strategy
       , [(Type, StrictnessMark)]   -- Rep types
       , (Unboxer, Boxer) )
index 48f5d99..6e14700 100644 (file)
@@ -128,7 +128,7 @@ mkNewTyConRhs tycon_name tycon con
 ------------------------------------------------------
 buildDataCon :: FamInstEnvs
             -> Name -> Bool
-            -> [HsSrcBang]
+            -> [HsBang]
             -> [Name]                   -- Field labels
             -> [TyVar] -> [TyVar]       -- Univ and ext
             -> [(TyVar,Type)]           -- Equality spec
index 0b17d61..9a0598e 100644 (file)
@@ -205,7 +205,8 @@ data IfaceConDecl
 
 type IfaceEqSpec = [(IfLclName,IfaceType)]
 
-data IfaceBang
+data IfaceBang  -- This corresponds to an HsImplBang; that is, the final
+                -- implementation decision about the data constructor arg
   = IfNoBang | IfStrict | IfUnpack | IfUnpackCo IfaceCoercion
 
 data IfaceClsInst
index 0d504e2..d76ce8d 100644 (file)
@@ -532,7 +532,10 @@ tcIfaceDataCons tycon_name tycon tc_tyvars if_cons
 
         ; con <- buildDataCon (pprPanic "tcIfaceDataCons: FamInstEnvs" (ppr name))
                        name is_infix
-                       stricts lbl_names
+                       stricts     -- Pass the HsImplBangs (i.e. final decisions
+                                   -- to buildDataCon; it'll use these to guide 
+                                   -- the construction of a worker
+                       lbl_names
                        tc_tyvars ex_tyvars
                        eq_spec theta
                        arg_tys orig_res_ty tycon
@@ -540,6 +543,7 @@ tcIfaceDataCons tycon_name tycon tc_tyvars if_cons
         ; return con }
     mk_doc con_name = ptext (sLit "Constructor") <+> ppr con_name
 
+    tc_strict :: IfaceBang -> IfL HsImplBang
     tc_strict IfNoBang = return HsNoBang
     tc_strict IfStrict = return HsStrict
     tc_strict IfUnpack = return (HsUnpack Nothing)