summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/basicTypes/DataCon.hs182
-rw-r--r--compiler/basicTypes/MkId.hs66
-rw-r--r--compiler/deSugar/DsMeta.hs12
-rw-r--r--compiler/hsSyn/Convert.hs4
-rw-r--r--compiler/hsSyn/HsTypes.hs6
-rw-r--r--compiler/iface/BuildTyCl.hs2
-rw-r--r--compiler/iface/MkIface.hs2
-rw-r--r--compiler/iface/TcIface.hs8
-rw-r--r--compiler/main/DynFlags.hs2
-rw-r--r--compiler/parser/Parser.y82
-rw-r--r--compiler/parser/RdrHsSyn.hs16
-rw-r--r--compiler/prelude/TysWiredIn.hs2
-rw-r--r--compiler/typecheck/TcExpr.hs4
-rw-r--r--compiler/typecheck/TcRnDriver.hs7
-rw-r--r--compiler/typecheck/TcSplice.hs13
-rw-r--r--compiler/typecheck/TcTyClsDecls.hs30
-rw-r--r--compiler/vectorise/Vectorise/Generic/PData.hs13
-rw-r--r--docs/users_guide/flags.xml12
-rw-r--r--docs/users_guide/glasgow_exts.xml68
-rw-r--r--testsuite/tests/deSugar/should_run/DsStrictData.hs48
-rw-r--r--testsuite/tests/deSugar/should_run/DsStrictData.stdout8
-rw-r--r--testsuite/tests/deSugar/should_run/all.T1
-rw-r--r--testsuite/tests/driver/T4437.hs4
m---------utils/haddock0
24 files changed, 395 insertions, 197 deletions
diff --git a/compiler/basicTypes/DataCon.hs b/compiler/basicTypes/DataCon.hs
index a70bcbdd3d..51b8d785d2 100644
--- a/compiler/basicTypes/DataCon.hs
+++ b/compiler/basicTypes/DataCon.hs
@@ -10,7 +10,8 @@
module DataCon (
-- * Main data types
DataCon, DataConRep(..),
- HsBang(..), HsSrcBang, HsImplBang,
+ HsBang(..), SrcStrictness(..), SrcUnpackedness(..),
+ HsSrcBang, HsImplBang,
StrictnessMark(..),
ConTag,
@@ -39,7 +40,7 @@ module DataCon (
-- ** Predicates on DataCons
isNullarySrcDataCon, isNullaryRepDataCon, isTupleDataCon, isUnboxedTupleCon,
isVanillaDataCon, classDataCon, dataConCannotMatch,
- isBanged, isMarkedStrict, eqHsBang,
+ isBanged, isMarkedStrict, eqHsBang, isSrcStrict, isSrcUnpacked,
-- ** Promotion related functions
promoteKind, promoteDataCon, promoteDataCon_maybe
@@ -348,12 +349,12 @@ data DataCon
-- Now the strictness annotations and field labels of the constructor
dcSrcBangs :: [HsBang],
-- See Note [Bangs on data constructor arguments]
- -- For DataCons defined in this module:
+ -- 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
@@ -447,38 +448,53 @@ data DataConRep
-- when we bring bits of unfoldings together.)
-------------------------
--- HsBang describes the strictness/unpack status of one
+-- | HsBang describes the strictness/unpack status of one
-- of the original data constructor arguments (i.e. *not*
-- of the representation data constructor which may have
-- more arguments after the originals have been unpacked)
-- See Note [Bangs on data constructor arguments]
data HsBang
- = HsNoBang -- Equivalent to (HsSrcBang Nothing False)
-
- | HsSrcBang -- What the user wrote in the source code
+ -- | What the user wrote in the source code.
+ --
+ -- (HsSrcBang _ SrcUnpack SrcLazy) and (HsSrcBang _ SrcUnpack
+ -- NoSrcStrictness) (without StrictData) makes no sense, we emit a
+ -- warning (in checkValidDataCon) and treat it like (HsSrcBang _
+ -- NoSrcUnpack SrcLazy)
+ = HsSrcBang
(Maybe SourceText) -- Note [Pragma source text] in BasicTypes
- (Maybe Bool) -- Just True {-# UNPACK #-}
- -- Just False {-# NOUNPACK #-}
- -- Nothing no pragma
- Bool -- True <=> '!' specified
- -- (HsSrcBang (Just True) False) makes no sense
- -- We emit a warning (in checkValidDataCon) and treat it
- -- just like (HsSrcBang Nothing False)
+ SrcUnpackedness
+ SrcStrictness
-- Definite implementation commitments, generated by the compiler
- -- after consulting HsSrcBang (if any), flags, etc
- | HsUnpack -- Definite commitment: this field is strict and unboxed
- (Maybe Coercion) -- co :: arg-ty ~ product-ty
+ -- after consulting HsSrcBang, flags, etc
+ | HsLazy -- ^ Definite commitment: Lazy field
+ | HsStrict -- ^ Definite commitment: Strict but not unpacked field
+ | HsUnpack (Maybe Coercion) -- co :: arg-ty ~ product-ty
+ -- ^ Definite commitment: Strict and unpacked field
- | HsStrict -- Definite commitment: this field is strict but not unboxed
deriving (Data.Data, Data.Typeable)
+-- | What strictness annotation the user wrote
+data SrcStrictness = SrcLazy -- ^ Lazy, ie '~'
+ | SrcStrict -- ^ Strict, ie '!'
+ | NoSrcStrictness -- ^ no strictness annotation
+ deriving (Eq, Data.Data, Data.Typeable)
+
+-- | What unpackedness the user requested
+data SrcUnpackedness = SrcUnpack -- ^ {-# UNPACK #-} specified
+ | SrcNoUnpack -- ^ {-# NOUNPACK #-} specified
+ | NoSrcUnpack -- ^ no unpack pragma
+ deriving (Eq, Data.Data, Data.Typeable)
+
+
-- Two type-insecure, but useful, synonyms
-type HsSrcBang = HsBang -- What the user wrote; hence always HsNoBang or HsSrcBang
-type HsImplBang = HsBang -- A HsBang implementation decision,
- -- as determined by the compiler
- -- Never HsSrcBang
+-- | What the user wrote; hence always HsSrcBang
+type HsSrcBang = HsBang
+
+-- | A HsBang implementation decision, as determined by the compiler.
+-- Never HsSrcBang
+type HsImplBang = HsBang
-------------------------
-- StrictnessMark is internal only, used to indicate strictness
@@ -492,38 +508,40 @@ Consider
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.
+flags like -funbox-small-strict-fields.
Terminology:
* HsSrcBang: What the user wrote
- Constructors: HsNoBang, HsUserBang
+ Constructors: HsSrcBang
* HsImplBang: What GHC decided
- Constructors: HsNoBang, HsStrict, HsUnpack
+ Constructors: HsLazy, HsStrict, HsUnpack
-* If T was defined in this module, MkT's dcSrcBangs field
+* 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]
+ [ HsSrcBang _ NoSrcUnpack SrcStrict
+ , HsSrcBang _ SrcUnpack SrcStrict
+ , HsSrcBang _ NoSrcUnpack NoSrcStrictness]
* However, if T was defined in an imported module, MkT's dcSrcBangs
- field gives the [HsImplBang] recording the decisions of the
+ 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]
+ [HsStrict, HsStrict, HsLazy]
With -O it might be
- [HsStrict, HsUnpack, HsNoBang]
+ [HsStrict, HsUnpack _, HsLazy]
With -funbox-small-strict-fields it might be
- [HsUnpack, HsUnpack, HsNoBang]
+ [HsUnpack, HsUnpack _, HsLazy]
+ With -XStrictData it might be
+ [HsStrict, HsUnpack _, HsStrict]
Note [Data con representation]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The dcRepType field contains the type of the representation of a contructor
-This may differ from the type of the contructor *Id* (built
+This may differ from the type of the constructor *Id* (built
by MkId.mkDataConId) for two reasons:
a) the constructor Id may be overloaded, but the dictionary isn't stored
e.g. data Eq a => T a = MkT a a
@@ -578,35 +596,51 @@ instance Data.Data DataCon where
dataTypeOf _ = mkNoRepType "DataCon"
instance Outputable HsBang where
- ppr HsNoBang = empty
- ppr (HsSrcBang _ prag bang) = pp_unpk prag <+> ppWhen bang (char '!')
- ppr (HsUnpack Nothing) = ptext (sLit "Unpk")
- ppr (HsUnpack (Just co)) = ptext (sLit "Unpk") <> parens (ppr co)
- ppr HsStrict = ptext (sLit "SrictNotUnpacked")
-
-pp_unpk :: Maybe Bool -> SDoc
-pp_unpk Nothing = empty
-pp_unpk (Just True) = ptext (sLit "{-# UNPACK #-}")
-pp_unpk (Just False) = ptext (sLit "{-# NOUNPACK #-}")
+ ppr (HsSrcBang _ prag mark) = ppr prag <+> ppr mark
+ ppr HsLazy = ptext (sLit "Lazy")
+ ppr (HsUnpack Nothing) = ptext (sLit "Unpacked")
+ ppr (HsUnpack (Just co)) = ptext (sLit "Unpacked") <> parens (ppr co)
+ ppr HsStrict = ptext (sLit "StrictNotUnpacked")
+
+instance Outputable SrcStrictness where
+ ppr SrcLazy = char '~'
+ ppr SrcStrict = char '!'
+ ppr NoSrcStrictness = empty
+
+instance Outputable SrcUnpackedness where
+ ppr SrcUnpack = ptext (sLit "{-# UNPACK #-}")
+ ppr SrcNoUnpack = ptext (sLit "{-# NOUNPACK #-}")
+ ppr NoSrcUnpack = empty
instance Outputable StrictnessMark where
ppr MarkedStrict = ptext (sLit "!")
ppr NotMarkedStrict = empty
+-- | Compare strictness annotations
eqHsBang :: HsBang -> HsBang -> Bool
-eqHsBang HsNoBang HsNoBang = True
-eqHsBang HsStrict HsStrict = True
-eqHsBang (HsSrcBang _ u1 b1) (HsSrcBang _ u2 b2) = u1==u2 && b1==b2
-eqHsBang (HsUnpack Nothing) (HsUnpack Nothing) = True
-eqHsBang (HsUnpack (Just c1)) (HsUnpack (Just c2)) = eqType (coercionType c1) (coercionType c2)
-eqHsBang _ _ = False
-
-isBanged :: HsBang -> Bool
-isBanged HsNoBang = False
-isBanged (HsSrcBang _ _ bang) = bang
-isBanged (HsUnpack {}) = True
-isBanged (HsStrict {}) = True
+eqHsBang (HsSrcBang _ u1 b1) (HsSrcBang _ u2 b2) = u1==u2 && b1==b2
+eqHsBang HsLazy HsLazy = True
+eqHsBang HsStrict HsStrict = True
+eqHsBang (HsUnpack Nothing) (HsUnpack Nothing) = True
+eqHsBang (HsUnpack (Just c1)) (HsUnpack (Just c2))
+ = eqType (coercionType c1) (coercionType c2)
+eqHsBang _ _ = False
+
+isBanged :: HsImplBang -> Bool
+isBanged (HsUnpack {}) = True
+isBanged (HsStrict {}) = True
+isBanged HsLazy = False
+isBanged (HsSrcBang {})
+ = panic "DataCon.isBanged: Cannot check bangedness of HsSrcBang."
+
+isSrcStrict :: SrcStrictness -> Bool
+isSrcStrict SrcStrict = True
+isSrcStrict _ = False
+
+isSrcUnpacked :: SrcUnpackedness -> Bool
+isSrcUnpacked SrcUnpack = True
+isSrcUnpacked _ = False
isMarkedStrict :: StrictnessMark -> Bool
isMarkedStrict NotMarkedStrict = False
@@ -622,22 +656,22 @@ isMarkedStrict _ = True -- All others are strict
-- | Build a new data constructor
mkDataCon :: Name
- -> Bool -- ^ Is the constructor declared infix?
- -> [HsBang] -- ^ Strictness/unpack annotations, from user;
- -- or, 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
- -> [TyVar] -- ^ Existentially quantified type variables
- -> [(TyVar,Type)] -- ^ GADT equalities
- -> ThetaType -- ^ Theta-type occuring before the arguments proper
- -> [Type] -- ^ Original argument types
- -> Type -- ^ Original result type
- -> TyCon -- ^ Representation type constructor
- -> ThetaType -- ^ The "stupid theta", context of the data declaration
- -- e.g. @data Eq a => T a ...@
- -> Id -- ^ Worker Id
- -> DataConRep -- ^ Representation
+ -> Bool -- ^ Is the constructor declared infix?
+ -> [HsBang] -- ^ Strictness/unpack annotations, from user; or,
+ -- 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
+ -> [TyVar] -- ^ Existentially quantified type variables
+ -> [(TyVar,Type)] -- ^ GADT equalities
+ -> ThetaType -- ^ Theta-type occuring before the arguments proper
+ -> [Type] -- ^ Original argument types
+ -> Type -- ^ Original result type
+ -> TyCon -- ^ Representation type constructor
+ -> ThetaType -- ^ The "stupid theta", context of the data
+ -- declaration e.g. @data Eq a => T a ...@
+ -> Id -- ^ Worker Id
+ -> DataConRep -- ^ Representation
-> DataCon
-- Can get the tag from the TyCon
@@ -835,7 +869,7 @@ dataConImplBangs :: DataCon -> [HsImplBang]
-- source program argument to the data constructor
dataConImplBangs dc
= case dcRep dc of
- NoDataConRep -> replicate (dcSourceArity dc) HsNoBang
+ NoDataConRep -> replicate (dcSourceArity dc) HsLazy
DCR { dcr_bangs = bangs } -> bangs
dataConBoxer :: DataCon -> Maybe DataConBoxer
diff --git a/compiler/basicTypes/MkId.hs b/compiler/basicTypes/MkId.hs
index 4edf26831f..bdcaf72864 100644
--- a/compiler/basicTypes/MkId.hs
+++ b/compiler/basicTypes/MkId.hs
@@ -490,7 +490,7 @@ mkDataConRep dflags fam_envs wrap_name data_con
wrap_sig = mkClosedStrictSig wrap_arg_dmds (dataConCPR data_con)
wrap_arg_dmds = map mk_dmd (dropList eq_spec wrap_bangs)
mk_dmd str | isBanged str = evalDmd
- | otherwise = topDmd
+ | otherwise = topDmd
-- 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
@@ -534,9 +534,9 @@ mkDataConRep dflags fam_envs wrap_name data_con
(rep_tys, rep_strs) = unzip (concat rep_tys_w_strs)
wrapper_reqd = not (isNewTyCon tycon) -- Newtypes have only a worker
- && (any isBanged orig_bangs -- Some forcing/unboxing
- -- (includes eq_spec)
- || isFamInstTyCon tycon) -- Cast result
+ && (any isBanged wrap_bangs -- Some forcing/unboxing
+ -- (includes eq_spec)
+ || isFamInstTyCon tycon) -- Cast result
initial_wrap_app = Var (dataConWorkId data_con)
`mkTyApps` res_ty_args
@@ -593,34 +593,42 @@ dataConArgRep
, [(Type, StrictnessMark)] -- Rep types
, (Unboxer, Boxer) )
-dataConArgRep _ _ arg_ty HsNoBang
- = (HsNoBang, [(arg_ty, NotMarkedStrict)], (unitUnboxer, unitBoxer))
+dataConArgRep dflags fam_envs arg_ty (HsSrcBang ann unpk NoSrcStrictness)
+ | xopt Opt_StrictData dflags -- StrictData => strict field
+ = dataConArgRep dflags fam_envs arg_ty (HsSrcBang ann unpk SrcStrict)
-dataConArgRep _ _ arg_ty (HsSrcBang _ _ False) -- No '!'
- = (HsNoBang, [(arg_ty, NotMarkedStrict)], (unitUnboxer, unitBoxer))
+ | otherwise -- no StrictData => lazy field
+ = (HsLazy, [(arg_ty, NotMarkedStrict)], (unitUnboxer, unitBoxer))
+
+dataConArgRep _ _ arg_ty (HsSrcBang _ _ SrcLazy)
+ = (HsLazy, [(arg_ty, NotMarkedStrict)], (unitUnboxer, unitBoxer))
dataConArgRep dflags fam_envs arg_ty
- (HsSrcBang _ unpk_prag True) -- {-# UNPACK #-} !
+ (HsSrcBang _ unpk_prag SrcStrict)
| not (gopt Opt_OmitInterfacePragmas dflags) -- Don't unpack if -fomit-iface-pragmas
-- Don't unpack if we aren't optimising; rather arbitrarily,
-- we use -fomit-iface-pragmas as the indication
, let mb_co = topNormaliseType_maybe fam_envs arg_ty
-- Unwrap type families and newtypes
arg_ty' = case mb_co of { Just (_,ty) -> ty; Nothing -> arg_ty }
- , isUnpackableType fam_envs arg_ty'
+ , isUnpackableType dflags fam_envs arg_ty'
, (rep_tys, wrappers) <- dataConArgUnpack arg_ty'
, case unpk_prag of
- Nothing -> gopt Opt_UnboxStrictFields dflags
- || (gopt Opt_UnboxSmallStrictFields dflags
- && length rep_tys <= 1) -- See Note [Unpack one-wide fields]
- Just unpack_me -> unpack_me
+ NoSrcUnpack ->
+ gopt Opt_UnboxStrictFields dflags
+ || (gopt Opt_UnboxSmallStrictFields dflags
+ && length rep_tys <= 1) -- See Note [Unpack one-wide fields]
+ srcUnpack -> isSrcUnpacked srcUnpack
= case mb_co of
Nothing -> (HsUnpack Nothing, rep_tys, wrappers)
Just (co,rep_ty) -> (HsUnpack (Just co), rep_tys, wrapCo co rep_ty wrappers)
- | otherwise -- Record the strict-but-no-unpack decision
+ | otherwise -- Record the strict-but-no-unpack decision
= strict_but_not_unpacked arg_ty
+dataConArgRep _ _ arg_ty HsLazy
+ = (HsLazy, [(arg_ty, NotMarkedStrict)], (unitUnboxer, unitBoxer))
+
dataConArgRep _ _ arg_ty HsStrict
= strict_but_not_unpacked arg_ty
@@ -695,13 +703,13 @@ dataConArgUnpack arg_ty
= pprPanic "dataConArgUnpack" (ppr arg_ty)
-- An interface file specified Unpacked, but we couldn't unpack it
-isUnpackableType :: FamInstEnvs -> Type -> Bool
+isUnpackableType :: DynFlags -> FamInstEnvs -> Type -> Bool
-- True if we can unpack the UNPACK the argument type
-- See Note [Recursive unboxing]
-- We look "deeply" inside rather than relying on the DataCons
-- we encounter on the way, because otherwise we might well
-- end up relying on ourselves!
-isUnpackableType fam_envs ty
+isUnpackableType dflags fam_envs ty
| Just (tc, _) <- splitTyConApp_maybe ty
, Just con <- tyConSingleAlgDataCon_maybe tc
, isVanillaDataCon con
@@ -728,11 +736,21 @@ isUnpackableType fam_envs ty
-- NB: dataConSrcBangs gives the *user* request;
-- We'd get a black hole if we used dataConImplBangs
- attempt_unpack (HsUnpack {}) = True
- attempt_unpack (HsSrcBang _ (Just unpk) bang) = bang && unpk
- attempt_unpack (HsSrcBang _ Nothing bang) = bang -- Be conservative
- attempt_unpack HsStrict = False
- attempt_unpack HsNoBang = False
+ attempt_unpack (HsUnpack {})
+ = True
+ attempt_unpack HsStrict
+ = False
+ attempt_unpack HsLazy
+ = False
+ attempt_unpack (HsSrcBang _ SrcUnpack NoSrcStrictness)
+ = xopt Opt_StrictData dflags
+ attempt_unpack (HsSrcBang _ SrcUnpack SrcStrict)
+ = True
+ attempt_unpack (HsSrcBang _ NoSrcUnpack SrcStrict)
+ = True -- Be conservative
+ attempt_unpack (HsSrcBang _ NoSrcUnpack NoSrcStrictness)
+ = xopt Opt_StrictData dflags -- Be conservative
+ attempt_unpack _ = False
{-
Note [Unpack one-wide fields]
@@ -797,10 +815,10 @@ heavy lifting. This one line makes every GADT take a word less
space for each equality predicate, so it's pretty important!
-}
-mk_pred_strict_mark :: PredType -> HsSrcBang
+mk_pred_strict_mark :: PredType -> HsImplBang
mk_pred_strict_mark pred
| isEqPred pred = HsUnpack Nothing -- Note [Unpack equality predicates]
- | otherwise = HsNoBang
+ | otherwise = HsLazy
{-
************************************************************************
diff --git a/compiler/deSugar/DsMeta.hs b/compiler/deSugar/DsMeta.hs
index d4a811ff1b..c222b33ed9 100644
--- a/compiler/deSugar/DsMeta.hs
+++ b/compiler/deSugar/DsMeta.hs
@@ -648,15 +648,17 @@ mkGadtCtxt data_tvs (ResTyGADT _ res_ty)
repBangTy :: LBangType Name -> DsM (Core (TH.StrictTypeQ))
-repBangTy ty= do
+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)
+ L _ (HsBangTy (HsSrcBang _ SrcUnpack SrcStrict) ty)
+ -> (unpackedName, ty)
+ L _ (HsBangTy (HsSrcBang _ _ SrcStrict) ty)
+ -> (isStrictName, ty)
+ _ -> (notStrictName, ty)
-------------------------------------------------------
-- Deriving clause
@@ -2129,5 +2131,3 @@ notHandled what doc = failWithDs msg
where
msg = hang (text what <+> ptext (sLit "not (yet) handled by Template Haskell"))
2 doc
-
-
diff --git a/compiler/hsSyn/Convert.hs b/compiler/hsSyn/Convert.hs
index 4a0e013cf9..d4a0b54c2a 100644
--- a/compiler/hsSyn/Convert.hs
+++ b/compiler/hsSyn/Convert.hs
@@ -438,10 +438,10 @@ cvt_arg :: (TH.Strict, TH.Type) -> CvtM (LHsType RdrName)
cvt_arg (NotStrict, ty) = cvtType ty
cvt_arg (IsStrict, ty)
= do { ty' <- cvtType ty
- ; returnL $ HsBangTy (HsSrcBang Nothing Nothing True) ty' }
+ ; returnL $ HsBangTy (HsSrcBang Nothing NoSrcUnpack SrcStrict) ty' }
cvt_arg (Unpacked, ty)
= do { ty' <- cvtType ty
- ; returnL $ HsBangTy (HsSrcBang Nothing (Just True) True) ty' }
+ ; returnL $ HsBangTy (HsSrcBang Nothing SrcUnpack SrcStrict) ty' }
cvt_id_arg :: (TH.Name, TH.Strict, TH.Type) -> CvtM (LConDeclField RdrName)
cvt_id_arg (i, str, ty)
diff --git a/compiler/hsSyn/HsTypes.hs b/compiler/hsSyn/HsTypes.hs
index 9526a8cce3..e123277851 100644
--- a/compiler/hsSyn/HsTypes.hs
+++ b/compiler/hsSyn/HsTypes.hs
@@ -29,6 +29,7 @@ module HsTypes (
HsIPName(..), hsIPNameFS,
LBangType, BangType, HsBang(..), HsSrcBang, HsImplBang,
+ SrcStrictness(..), SrcUnpackedness(..),
getBangType, getBangStrictness,
ConDeclField(..), LConDeclField, pprConDeclFields,
@@ -62,7 +63,8 @@ import PlaceHolder ( PostTc,PostRn,DataId,PlaceHolder(..) )
import Name( Name )
import RdrName( RdrName )
-import DataCon( HsBang(..), HsSrcBang, HsImplBang )
+import DataCon( HsBang(..), HsSrcBang, HsImplBang,
+ SrcStrictness(..), SrcUnpackedness(..) )
import TysPrim( funTyConName )
import Type
import HsDoc
@@ -97,7 +99,7 @@ getBangType ty = ty
getBangStrictness :: LHsType a -> HsSrcBang
getBangStrictness (L _ (HsBangTy s _)) = s
-getBangStrictness _ = HsNoBang
+getBangStrictness _ = HsSrcBang Nothing NoSrcUnpack NoSrcStrictness
{-
************************************************************************
diff --git a/compiler/iface/BuildTyCl.hs b/compiler/iface/BuildTyCl.hs
index b6db5dc9ee..28a5f68f47 100644
--- a/compiler/iface/BuildTyCl.hs
+++ b/compiler/iface/BuildTyCl.hs
@@ -272,7 +272,7 @@ buildClass tycon_name tvs roles sc_theta fds at_items sig_stuff mindef tc_isrec
; dict_con <- buildDataCon (panic "buildClass: FamInstEnvs")
datacon_name
False -- Not declared infix
- (map (const HsNoBang) args)
+ (map (const HsLazy) args)
[{- No fields -}]
tvs [{- no existentials -}]
[{- No GADT equalities -}]
diff --git a/compiler/iface/MkIface.hs b/compiler/iface/MkIface.hs
index 753c81a8a0..2b8a21272e 100644
--- a/compiler/iface/MkIface.hs
+++ b/compiler/iface/MkIface.hs
@@ -1728,7 +1728,7 @@ tyConToIfaceDecl env tycon
to_eq_spec (tv,ty) = (toIfaceTyVar (tidyTyVar con_env2 tv), tidyToIfaceType con_env2 ty)
toIfaceBang :: TidyEnv -> HsImplBang -> IfaceBang
-toIfaceBang _ HsNoBang = IfNoBang
+toIfaceBang _ HsLazy = IfNoBang
toIfaceBang _ (HsUnpack Nothing) = IfUnpack
toIfaceBang env (HsUnpack (Just co)) = IfUnpackCo (toIfaceCoercion (tidyCo env co))
toIfaceBang _ HsStrict = IfStrict
diff --git a/compiler/iface/TcIface.hs b/compiler/iface/TcIface.hs
index a7c340f780..3e977474b1 100644
--- a/compiler/iface/TcIface.hs
+++ b/compiler/iface/TcIface.hs
@@ -542,9 +542,9 @@ tcIfaceDataCons tycon_name tycon tc_tyvars if_cons
; con <- buildDataCon (pprPanic "tcIfaceDataCons: FamInstEnvs" (ppr name))
name is_infix
- stricts -- Pass the HsImplBangs (i.e. final decisions
- -- to buildDataCon; it'll use these to guide
- -- the construction of a worker
+ 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
@@ -554,7 +554,7 @@ tcIfaceDataCons tycon_name tycon tc_tyvars if_cons
mk_doc con_name = ptext (sLit "Constructor") <+> ppr con_name
tc_strict :: IfaceBang -> IfL HsImplBang
- tc_strict IfNoBang = return HsNoBang
+ tc_strict IfNoBang = return HsLazy
tc_strict IfStrict = return HsStrict
tc_strict IfUnpack = return (HsUnpack Nothing)
tc_strict (IfUnpackCo if_co) = do { co <- tcIfaceCo if_co
diff --git a/compiler/main/DynFlags.hs b/compiler/main/DynFlags.hs
index 74e9bf303d..35e5dc5fc5 100644
--- a/compiler/main/DynFlags.hs
+++ b/compiler/main/DynFlags.hs
@@ -653,6 +653,7 @@ data ExtensionFlag
| Opt_PartialTypeSignatures
| Opt_NamedWildCards
| Opt_StaticPointers
+ | Opt_StrictData
deriving (Eq, Enum, Show)
type SigOf = Map ModuleName Module
@@ -3207,6 +3208,7 @@ xFlags = [
flagSpec "ScopedTypeVariables" Opt_ScopedTypeVariables,
flagSpec "StandaloneDeriving" Opt_StandaloneDeriving,
flagSpec "StaticPointers" Opt_StaticPointers,
+ flagSpec "StrictData" Opt_StrictData,
flagSpec' "TemplateHaskell" Opt_TemplateHaskell
setTemplateHaskellLoc,
flagSpec "TraditionalRecordSyntax" Opt_TraditionalRecordSyntax,
diff --git a/compiler/parser/Parser.y b/compiler/parser/Parser.y
index 99abf162d1..815c8cb798 100644
--- a/compiler/parser/Parser.y
+++ b/compiler/parser/Parser.y
@@ -1566,18 +1566,21 @@ sigtypes1 :: { (OrdList (LHsType RdrName)) } -- Always HsForAllTys
-- Types
strict_mark :: { Located ([AddAnn],HsBang) }
- : '!' { sL1 $1 ([mj AnnBang $1]
- ,HsSrcBang Nothing Nothing True) }
- | '{-# UNPACK' '#-}' { sLL $1 $> ([mo $1,mc $2]
- ,HsSrcBang (Just $ getUNPACK_PRAGs $1) (Just True) False) }
- | '{-# NOUNPACK' '#-}' { sLL $1 $> ([mo $1,mc $2]
- ,HsSrcBang (Just $ getNOUNPACK_PRAGs $1) (Just False) False) }
- | '{-# UNPACK' '#-}' '!' { sLL $1 $> ([mo $1,mc $2,mj AnnBang $3]
- ,HsSrcBang (Just $ getUNPACK_PRAGs $1) (Just True) True) }
- | '{-# NOUNPACK' '#-}' '!' { sLL $1 $> ([mo $1,mc $2,mj AnnBang $3]
- ,HsSrcBang (Just $ getNOUNPACK_PRAGs $1) (Just False) True) }
- -- Although UNPACK with no '!' is illegal, we get a
- -- better error message if we parse it here
+ : strictness { sL1 $1 (let (a, str) = unLoc $1 in (a, HsSrcBang Nothing NoSrcUnpack str)) }
+ | unpackedness { sL1 $1 (let (a, prag, unpk) = unLoc $1 in (a, HsSrcBang prag unpk NoSrcStrictness)) }
+ | unpackedness strictness { sLL $1 $> (let { (a, prag, unpk) = unLoc $1
+ ; (a', str) = unLoc $2 }
+ in (a ++ a', HsSrcBang prag unpk str)) }
+ -- Although UNPACK with no '!' without StrictData and UNPACK with '~' are illegal,
+ -- we get a better error message if we parse them here
+
+strictness :: { Located ([AddAnn], SrcStrictness) }
+ : '!' { sL1 $1 ([mj AnnBang $1], SrcStrict) }
+ | '~' { sL1 $1 ([mj AnnTilde $1], SrcLazy) }
+
+unpackedness :: { Located ([AddAnn], Maybe SourceText, SrcUnpackedness) }
+ : '{-# UNPACK' '#-}' { sLL $1 $> ([mo $1, mc $2], Just $ getUNPACK_PRAGs $1, SrcUnpack) }
+ | '{-# NOUNPACK' '#-}' { sLL $1 $> ([mo $1, mc $2], Just $ getNOUNPACK_PRAGs $1, SrcNoUnpack) }
-- A ctype is a for-all type
ctype :: { LHsType RdrName }
@@ -1626,47 +1629,39 @@ ctypedoc :: { LHsType RdrName }
-- to permit an individual equational constraint without parenthesis.
-- Thus for some reason we allow f :: a~b => blah
-- but not f :: ?x::Int => blah
+-- See Note [Parsing ~]
context :: { LHsContext RdrName }
- : btype '~' btype {% do { (anns,ctx) <- checkContext
- (sLL $1 $> $ HsEqTy $1 $3)
- ; ams ctx (mj AnnTilde $2:anns) } }
- | btype {% do { (anns,ctx) <- checkContext $1
- ; if null (unLoc ctx)
- then addAnnotation (gl $1) AnnUnit (gl $1)
- else return ()
- ; ams ctx anns
- } }
-
+ : btype {% do { (anns,ctx) <- checkContext (splitTilde $1)
+ ; if null (unLoc ctx)
+ then addAnnotation (gl $1) AnnUnit (gl $1)
+ else return ()
+ ; ams ctx anns
+ } }
+-- See Note [Parsing ~]
type :: { LHsType RdrName }
- : btype { $1 }
+ : btype { splitTilde $1 }
| btype qtyconop type { sLL $1 $> $ mkHsOpTy $1 $2 $3 }
| btype tyvarop type { sLL $1 $> $ mkHsOpTy $1 $2 $3 }
| btype '->' ctype {% ams $1 [mj AnnRarrow $2]
- >> ams (sLL $1 $> $ HsFunTy $1 $3)
+ >> ams (sLL $1 $> $ HsFunTy (splitTilde $1) $3)
[mj AnnRarrow $2] }
- | btype '~' btype {% ams (sLL $1 $> $ HsEqTy $1 $3)
- [mj AnnTilde $2] }
- -- see Note [Promotion]
| btype SIMPLEQUOTE qconop type {% ams (sLL $1 $> $ mkHsOpTy $1 $3 $4)
[mj AnnSimpleQuote $2] }
| btype SIMPLEQUOTE varop type {% ams (sLL $1 $> $ mkHsOpTy $1 $3 $4)
[mj AnnSimpleQuote $2] }
-
+-- See Note [Parsing ~]
typedoc :: { LHsType RdrName }
- : btype { $1 }
- | btype docprev { sLL $1 $> $ HsDocTy $1 $2 }
+ : btype { splitTilde $1 }
+ | btype docprev { sLL $1 $> $ HsDocTy (splitTilde $1) $2 }
| btype qtyconop type { sLL $1 $> $ mkHsOpTy $1 $2 $3 }
| btype qtyconop type docprev { sLL $1 $> $ HsDocTy (L (comb3 $1 $2 $3) (mkHsOpTy $1 $2 $3)) $4 }
| btype tyvarop type { sLL $1 $> $ mkHsOpTy $1 $2 $3 }
| btype tyvarop type docprev { sLL $1 $> $ HsDocTy (L (comb3 $1 $2 $3) (mkHsOpTy $1 $2 $3)) $4 }
- | btype '->' ctypedoc {% ams (sLL $1 $> $ HsFunTy $1 $3)
+ | btype '->' ctypedoc {% ams (sLL $1 $> $ HsFunTy (splitTilde $1) $3)
[mj AnnRarrow $2] }
- | btype docprev '->' ctypedoc {% ams (sLL $1 $> $ HsFunTy (L (comb2 $1 $2)
+ | btype docprev '->' ctypedoc {% ams (sLL $1 $> $ HsFunTy (L (comb2 (splitTilde $1) $2)
(HsDocTy $1 $2)) $4)
[mj AnnRarrow $3] }
- | btype '~' btype {% ams (sLL $1 $> $ HsEqTy $1 $3)
- [mj AnnTilde $2] }
- -- see Note [Promotion]
| btype SIMPLEQUOTE qconop type {% ams (sLL $1 $> $ mkHsOpTy $1 $3 $4)
[mj AnnSimpleQuote $2] }
| btype SIMPLEQUOTE varop type {% ams (sLL $1 $> $ mkHsOpTy $1 $3 $4)
@@ -1791,6 +1786,23 @@ varids0 :: { Located [Located RdrName] }
: {- empty -} { noLoc [] }
| varids0 tyvar { sLL $1 $> ($2 : unLoc $1) }
+{-
+Note [Parsing ~]
+~~~~~~~~~~~~~~~~
+
+Due to parsing conflicts between lazyness annotations in data type
+declarations (see strict_mark) and equality types ~'s are always
+parsed as lazyness annotations, and turned into HsEqTy's in the
+correct places using RdrHsSyn.splitTilde.
+
+Since strict_mark is parsed as part of atype which is part of type,
+typedoc and context (where HsEqTy previously appeared) it made most
+sense and was simplest to parse ~ as part of strict_mark and later
+turn them into HsEqTy's.
+
+-}
+
+
-----------------------------------------------------------------------------
-- Kinds
diff --git a/compiler/parser/RdrHsSyn.hs b/compiler/parser/RdrHsSyn.hs
index aa0b8cf16f..357512be33 100644
--- a/compiler/parser/RdrHsSyn.hs
+++ b/compiler/parser/RdrHsSyn.hs
@@ -52,6 +52,7 @@ module RdrHsSyn (
checkDoAndIfThenElse,
checkRecordSyntax,
parseErrorSDoc,
+ splitTilde,
-- Help with processing exports
ImpExpSubSpec(..),
@@ -1059,6 +1060,21 @@ isFunLhs e = go e [] []
go _ _ _ = return Nothing
+-- | Transform btype with strict_mark's into HsEqTy's
+-- (((~a) ~b) c) ~d ==> ((~a) ~ (b c)) ~ d
+splitTilde :: LHsType RdrName -> LHsType RdrName
+splitTilde t = go t
+ where go (L loc (HsAppTy t1 t2))
+ | L _ (HsBangTy (HsSrcBang Nothing NoSrcUnpack SrcLazy) t2') <- t2
+ = L loc (HsEqTy (go t1) t2')
+ | otherwise
+ = case go t1 of
+ (L _ (HsEqTy tl tr)) ->
+ L loc (HsEqTy tl (L (combineLocs tr t2) (HsAppTy tr t2)))
+ t -> L loc (HsAppTy t t2)
+
+ go t = t
+
---------------------------------------------------------------------------
-- Check for monad comprehensions
--
diff --git a/compiler/prelude/TysWiredIn.hs b/compiler/prelude/TysWiredIn.hs
index f7d08ff1c4..83599682e9 100644
--- a/compiler/prelude/TysWiredIn.hs
+++ b/compiler/prelude/TysWiredIn.hs
@@ -285,7 +285,7 @@ pcDataConWithFixity' declared_infix dc_name wrk_key tyvars arg_tys tycon
= data_con
where
data_con = mkDataCon dc_name declared_infix
- (map (const HsNoBang) arg_tys)
+ (map (const HsLazy) arg_tys)
[] -- No labelled fields
tyvars
[] -- No existential type variables
diff --git a/compiler/typecheck/TcExpr.hs b/compiler/typecheck/TcExpr.hs
index cc09d23554..605ba57089 100644
--- a/compiler/typecheck/TcExpr.hs
+++ b/compiler/typecheck/TcExpr.hs
@@ -1371,7 +1371,7 @@ tcRecordBinds data_con arg_tys (HsRecFields rbinds dd)
= do { addErrTc (badFieldCon (RealDataCon data_con) field_lbl)
; return Nothing }
-checkMissingFields :: DataCon -> HsRecordBinds Name -> TcM ()
+checkMissingFields :: DataCon -> HsRecordBinds Name -> TcM ()
checkMissingFields data_con rbinds
| null field_labels -- Not declared as a record;
-- But C{} is still valid if no strict fields
@@ -1408,7 +1408,7 @@ checkMissingFields data_con rbinds
field_labels
field_strs
- field_strs = dataConSrcBangs data_con
+ field_strs = dataConImplBangs data_con
{-
************************************************************************
diff --git a/compiler/typecheck/TcRnDriver.hs b/compiler/typecheck/TcRnDriver.hs
index c46a2174d5..010a67940f 100644
--- a/compiler/typecheck/TcRnDriver.hs
+++ b/compiler/typecheck/TcRnDriver.hs
@@ -838,8 +838,8 @@ checkBootDeclM :: Bool -- ^ True <=> an hs-boot file (could also be a sig)
-> TyThing -> TyThing -> TcM ()
checkBootDeclM is_boot boot_thing real_thing
= whenIsJust (checkBootDecl boot_thing real_thing) $ \ err ->
- addErrAt (nameSrcSpan (getName boot_thing))
- (bootMisMatch is_boot err real_thing boot_thing)
+ addErrAt (nameSrcSpan (getName boot_thing))
+ (bootMisMatch is_boot err real_thing boot_thing)
-- | Compares the two things for equivalence between boot-file and normal
-- code. Returns @Nothing@ on success or @Just "some helpful info for user"@
@@ -1017,8 +1017,7 @@ checkBootTyCon tc1 tc2
check (dataConIsInfix c1 == dataConIsInfix c2)
(text "The fixities of" <+> pname1 <+>
text "differ") `andThenCheck`
- check (eqListBy eqHsBang
- (dataConSrcBangs c1) (dataConSrcBangs c2))
+ check (eqListBy eqHsBang (dataConImplBangs c1) (dataConImplBangs c2))
(text "The strictness annotations for" <+> pname1 <+>
text "differ") `andThenCheck`
check (dataConFieldLabels c1 == dataConFieldLabels c2)
diff --git a/compiler/typecheck/TcSplice.hs b/compiler/typecheck/TcSplice.hs
index d8dde3346e..4a414a2d43 100644
--- a/compiler/typecheck/TcSplice.hs
+++ b/compiler/typecheck/TcSplice.hs
@@ -1490,12 +1490,13 @@ reifyFixity name
conv_dir BasicTypes.InfixN = TH.InfixN
reifyStrict :: DataCon.HsSrcBang -> TH.Strict
-reifyStrict HsNoBang = TH.NotStrict
-reifyStrict (HsSrcBang _ _ False) = TH.NotStrict
-reifyStrict (HsSrcBang _ (Just True) True) = TH.Unpacked
-reifyStrict (HsSrcBang _ _ True) = TH.IsStrict
-reifyStrict HsStrict = TH.IsStrict
-reifyStrict (HsUnpack {}) = TH.Unpacked
+reifyStrict HsLazy = TH.NotStrict
+reifyStrict (HsSrcBang _ _ SrcLazy) = TH.NotStrict
+reifyStrict (HsSrcBang _ _ NoSrcStrictness) = TH.NotStrict
+reifyStrict (HsSrcBang _ SrcUnpack SrcStrict) = TH.Unpacked
+reifyStrict (HsSrcBang _ _ SrcStrict) = TH.IsStrict
+reifyStrict HsStrict = TH.IsStrict
+reifyStrict (HsUnpack {}) = TH.Unpacked
------------------------------
lookupThAnnLookup :: TH.AnnLookup -> TcM CoreAnnTarget
diff --git a/compiler/typecheck/TcTyClsDecls.hs b/compiler/typecheck/TcTyClsDecls.hs
index 9c14055c08..b7a959e207 100644
--- a/compiler/typecheck/TcTyClsDecls.hs
+++ b/compiler/typecheck/TcTyClsDecls.hs
@@ -1613,15 +1613,24 @@ checkValidDataCon dflags existential_ok tc con
}
where
ctxt = ConArgCtxt (dataConName con)
- check_bang (HsSrcBang _ (Just want_unpack) has_bang, rep_bang, n)
- | want_unpack, not has_bang
+
+ check_bang (HsSrcBang _ _ SrcLazy, _, n)
+ | not (xopt Opt_StrictData dflags)
+ = addErrTc
+ (bad_bang n (ptext (sLit "Lazy annotation (~) without StrictData")))
+ check_bang (HsSrcBang _ want_unpack strict_mark, rep_bang, n)
+ | isSrcUnpacked want_unpack, not is_strict
= addWarnTc (bad_bang n (ptext (sLit "UNPACK pragma lacks '!'")))
- | want_unpack
+ | isSrcUnpacked want_unpack
, case rep_bang of { HsUnpack {} -> False; _ -> True }
, not (gopt Opt_OmitInterfacePragmas dflags)
-- If not optimising, se don't unpack, so don't complain!
-- See MkId.dataConArgRep, the (HsBang True) case
= addWarnTc (bad_bang n (ptext (sLit "Ignoring unusable UNPACK pragma")))
+ where
+ is_strict = case strict_mark of
+ NoSrcStrictness -> xopt Opt_StrictData dflags
+ bang -> isSrcStrict bang
check_bang _
= return ()
@@ -1634,7 +1643,7 @@ checkNewDataCon :: DataCon -> TcM ()
-- Further checks for the data constructor of a newtype
checkNewDataCon con
= do { checkTc (isSingleton arg_tys) (newtypeFieldErr con (length arg_tys))
- -- One argument
+ -- One argument
; check_con (null eq_spec) $
ptext (sLit "A newtype constructor must have a return type of form T a1 ... an")
@@ -1647,15 +1656,20 @@ checkNewDataCon con
ptext (sLit "A newtype constructor cannot have existential type variables")
-- No existentials
- ; checkTc (not (any isBanged (dataConSrcBangs con)))
+ ; checkTc (all ok_bang (dataConSrcBangs con))
(newtypeStrictError con)
- -- No strictness
+ -- No strictness annotations
}
where
(_univ_tvs, ex_tvs, eq_spec, theta, arg_tys, _res_ty) = dataConFullSig con
+
check_con what msg
= checkTc what (msg $$ ppr con <+> dcolon <+> ppr (dataConUserType con))
+ ok_bang (HsSrcBang _ _ SrcStrict) = False
+ ok_bang (HsSrcBang _ _ SrcLazy) = False
+ ok_bang _ = True
+
-------------------------------
checkValidClass :: Class -> TcM ()
checkValidClass cls
@@ -1704,7 +1718,7 @@ checkValidClass cls
-- Here, MonadState has a fundep m->b, so newBoard is fine
; unless constrained_class_methods $
- mapM_ check_constraint (tail (theta1 ++ theta2))
+ mapM_ check_constraint (tail (theta1 ++ theta2))
; case dm of
GenDefMeth dm_name -> do { dm_id <- tcLookupId dm_name
@@ -2164,7 +2178,7 @@ classFunDepsErr cls
badMethPred :: Id -> TcPredType -> SDoc
badMethPred sel_id pred
- = vcat [ hang (ptext (sLit "Constraint") <+> quotes (ppr pred)
+ = vcat [ hang (ptext (sLit "Constraint") <+> quotes (ppr pred)
<+> ptext (sLit "in the type of") <+> quotes (ppr sel_id))
2 (ptext (sLit "constrains only the class type variables"))
, ptext (sLit "Use ConstrainedClassMethods to allow it") ]
diff --git a/compiler/vectorise/Vectorise/Generic/PData.hs b/compiler/vectorise/Vectorise/Generic/PData.hs
index ed127b449f..e9a1133348 100644
--- a/compiler/vectorise/Vectorise/Generic/PData.hs
+++ b/compiler/vectorise/Vectorise/Generic/PData.hs
@@ -5,7 +5,7 @@
-- We should be able to factor out the common parts.
module Vectorise.Generic.PData
( buildPDataTyCon
- , buildPDatasTyCon )
+ , buildPDatasTyCon )
where
import Vectorise.Monad
@@ -31,7 +31,7 @@ import Control.Monad
-- buildPDataTyCon ------------------------------------------------------------
-- | Build the PData instance tycon for a given type constructor.
buildPDataTyCon :: TyCon -> TyCon -> SumRepr -> VM FamInst
-buildPDataTyCon orig_tc vect_tc repr
+buildPDataTyCon orig_tc vect_tc repr
= fixV $ \fam_inst ->
do let repr_tc = dataFamInstRepTyCon fam_inst
name' <- mkLocalisedName mkPDataTyConOcc orig_name
@@ -79,7 +79,7 @@ buildPDataDataCon orig_name vect_tc repr_tc repr
fam_envs <- readGEnv global_fam_inst_env
liftDs $ buildDataCon fam_envs dc_name
False -- not infix
- (map (const HsNoBang) comp_tys)
+ (map (const HsLazy) comp_tys)
[] -- no field labels
tvs
[] -- no existentials
@@ -93,7 +93,7 @@ buildPDataDataCon orig_name vect_tc repr_tc repr
-- buildPDatasTyCon -----------------------------------------------------------
-- | Build the PDatas instance tycon for a given type constructor.
buildPDatasTyCon :: TyCon -> TyCon -> SumRepr -> VM FamInst
-buildPDatasTyCon orig_tc vect_tc repr
+buildPDatasTyCon orig_tc vect_tc repr
= fixV $ \fam_inst ->
do let repr_tc = dataFamInstRepTyCon fam_inst
name' <- mkLocalisedName mkPDatasTyConOcc orig_name
@@ -118,7 +118,7 @@ buildPDatasDataCon orig_name vect_tc repr_tc repr
fam_envs <- readGEnv global_fam_inst_env
liftDs $ buildDataCon fam_envs dc_name
False -- not infix
- (map (const HsNoBang) comp_tys)
+ (map (const HsLazy) comp_tys)
[] -- no field labels
tvs
[] -- no existentials
@@ -131,7 +131,7 @@ buildPDatasDataCon orig_name vect_tc repr_tc repr
-- Utils ----------------------------------------------------------------------
-- | Flatten a SumRepr into a list of data constructor types.
-mkSumTys
+mkSumTys
:: (SumRepr -> Type)
-> (Type -> VM Type)
-> SumRepr
@@ -158,4 +158,3 @@ mk_fam_inst :: TyCon -> TyCon -> (TyCon, [Type])
mk_fam_inst fam_tc arg_tc
= (fam_tc, [mkTyConApp arg_tc . mkTyVarTys $ tyConTyVars arg_tc])
-}
-
diff --git a/docs/users_guide/flags.xml b/docs/users_guide/flags.xml
index c9186006d6..39b48722c1 100644
--- a/docs/users_guide/flags.xml
+++ b/docs/users_guide/flags.xml
@@ -720,7 +720,7 @@
<tbody>
<row>
<entry><option>-fconstraint-solver-iterations=</option><replaceable>n</replaceable></entry>
- <entry>Set the iteration limit for the type-constraint solver.
+ <entry>Set the iteration limit for the type-constraint solver.
The default limit is 4. Typically one iteration
suffices; so please yell if you find you need to set
it higher than the default. Zero means infinity. </entry>
@@ -729,7 +729,7 @@
</row>
<row>
<entry><option>-freduction-depth=</option><replaceable>n</replaceable></entry>
- <entry>Set the <link linkend="undecidable-instances">limit for type simplification</link>.
+ <entry>Set the <link linkend="undecidable-instances">limit for type simplification</link>.
Default is 200; zero means infinity.</entry>
<entry>dynamic</entry>
<entry></entry>
@@ -1309,7 +1309,7 @@
</row>
<row>
<entry><option>-XRelaxedPolyRec</option></entry>
- <entry><emphasis>(deprecated)</emphasis> Relaxed checking for
+ <entry><emphasis>(deprecated)</emphasis> Relaxed checking for
<link linkend="typing-binds">mutually-recursive polymorphic functions</link>.</entry>
<entry>dynamic</entry>
<entry><option>-XNoRelaxedPolyRec</option></entry>
@@ -1345,6 +1345,12 @@
<entry>6.8.1</entry>
</row>
<row>
+ <entry><option>-XStrictData</option></entry>
+ <entry>Enable <link linkend="strict-data">default strict datatype fields</link>.</entry>
+ <entry>dynamic</entry>
+ <entry><option>-XNoStrictData</option></entry>
+ </row>
+ <row>
<entry><option>-XTemplateHaskell</option></entry>
<entry>Enable <link linkend="template-haskell">Template Haskell</link>.</entry>
<entry>dynamic</entry>
diff --git a/docs/users_guide/glasgow_exts.xml b/docs/users_guide/glasgow_exts.xml
index 9685b1d29a..e3368f2129 100644
--- a/docs/users_guide/glasgow_exts.xml
+++ b/docs/users_guide/glasgow_exts.xml
@@ -1114,7 +1114,7 @@ on <literal>MkT</literal>. But the same pattern match also <emphasis>provides</e
</para>
<para>
Exactly the same reasoning applies to <literal>ExNumPat</literal>:
-matching against <literal>ExNumPat</literal> <emphasis>requires</emphasis>
+matching against <literal>ExNumPat</literal> <emphasis>requires</emphasis>
the constraints <literal>(Num a, Eq a)</literal>, and <emphasis>provides</emphasis>
the constraint <literal>(Show b)</literal>.
</para>
@@ -4707,7 +4707,7 @@ class type variable (in this case <literal>a</literal>).
</para>
<para>
GHC lifts this restriction with language extension <option>-XConstrainedClassMethods</option>.
-The restriction is a pretty stupid one in the first place,
+The restriction is a pretty stupid one in the first place,
so <option>-XConstrainedClassMethods</option> is implied by <option>-XMultiParamTypeClasses</option>.
</para>
</sect3>
@@ -5235,7 +5235,7 @@ termination: see <xref linkend="instance-termination"/>.
<para>
Regardless of <option>-XFlexibleInstances</option> and <option>-XFlexibleContexts</option>,
instance declarations must conform to some rules that ensure that instance resolution
-will terminate. The restrictions can be lifted with <option>-XUndecidableInstances</option>
+will terminate. The restrictions can be lifted with <option>-XUndecidableInstances</option>
(see <xref linkend="undecidable-instances"/>).
</para>
<para>
@@ -6908,8 +6908,8 @@ T :: (k -> *) -> k -> *
</para></listitem>
<listitem><para>
-GHC does not usually print explicit <literal>forall</literal>s, including kind <literal>forall</literal>s.
-You can make GHC show them explicitly with <option>-fprint-explicit-foralls</option>
+GHC does not usually print explicit <literal>forall</literal>s, including kind <literal>forall</literal>s.
+You can make GHC show them explicitly with <option>-fprint-explicit-foralls</option>
(see <xref linkend="options-help"/>):
<programlisting>
ghci> :set -XPolyKinds
@@ -6981,7 +6981,7 @@ very convenient, and it is not clear what the syntax for explicit quantification
Generally speaking, when <option>-XPolyKinds</option> is on, GHC tries to infer the most
general kind for a declaration. For example:
<programlisting>
-data T f a = MkT (f a) -- GHC infers:
+data T f a = MkT (f a) -- GHC infers:
-- T :: forall k. (k->*) -> k -> *
</programlisting>
In this case the definition has a right-hand side to inform kind inference.
@@ -6990,9 +6990,9 @@ But that is not always the case. Consider
type family F a
</programlisting>
Type family declarations have no right-hand side, but GHC must still infer a kind
-for <literal>F</literal>. Since there are no constraints, it could infer
-<literal>F :: forall k1 k2. k1 -> k2</literal>, but that seems <emphasis>too</emphasis>
-polymorphic. So GHC defaults those entirely-unconstrained kind variables to <literal>*</literal> and
+for <literal>F</literal>. Since there are no constraints, it could infer
+<literal>F :: forall k1 k2. k1 -> k2</literal>, but that seems <emphasis>too</emphasis>
+polymorphic. So GHC defaults those entirely-unconstrained kind variables to <literal>*</literal> and
we get <literal>F :: * -> *</literal>. You can still declare <literal>F</literal> to be
kind-polymorphic using kind signatures:
<programlisting>
@@ -7014,23 +7014,23 @@ by the class method signatures.
</para></listitem>
<listitem><para>
<emphasis>When there is no right hand side, GHC defaults argument and result kinds to <literal>*</literal>,
-except when directed otherwise by a kind signature</emphasis>.
+except when directed otherwise by a kind signature</emphasis>.
Examples: data and type family declarations.
</para></listitem>
</itemizedlist>
-This rule has occasionally-surprising consequences
+This rule has occasionally-surprising consequences
(see <ulink url="https://ghc.haskell.org/trac/ghc/ticket/10132">Trac 10132</ulink>).
<programlisting>
class C a where -- Class declarations are generalised
-- so C :: forall k. k -> Constraint
- data D1 a -- No right hand side for these two family
+ data D1 a -- No right hand side for these two family
type F1 a -- declarations, but the class forces (a :: k)
-- so D1, F1 :: forall k. k -> *
data D2 a -- No right-hand side so D2 :: * -> *
type F2 a -- No right-hand side so F2 :: * -> *
</programlisting>
-The kind-polymorphism from the class declaration makes <literal>D1</literal>
+The kind-polymorphism from the class declaration makes <literal>D1</literal>
kind-polymorphic, but not so <literal>D2</literal>; and similarly <literal>F1</literal>, <literal>F1</literal>.
</para>
</sect2>
@@ -8500,7 +8500,7 @@ for rank-2 types.
<title>Impredicative polymorphism
</title>
<para>In general, GHC will only instantiate a polymorphic function at
-a monomorphic type (one with no foralls). For example,
+a monomorphic type (one with no foralls). For example,
<programlisting>
runST :: (forall s. ST s a) -> a
id :: forall b. b -> b
@@ -13303,10 +13303,48 @@ Here are some examples:</para>
</sect1>
+<sect1 id="strict-haskell">
+ <title>Strict Haskell</title>
+ <indexterm><primary>strict haskell</primary></indexterm>
+
+ <para>High-performance Haskell code (e.g. numeric code) can
+ sometimes be littered with bang patterns, making it harder to
+ read. The reason is that lazy evaluation isn't the right default in
+ this particular code but the programmer has no way to say that
+ except by repeatedly adding bang patterns. Below
+ <option>-XStrictData</option> is detailed that allows the programmer
+ to switch the default behavior on a per-module basis.</para>
+
+ <sect2 id="strict-data">
+ <title>Strict-by-default data types</title>
+
+ <para>Informally the <literal>StrictData</literal> language
+ extension switches data type declarations to be strict by default
+ allowing fields to be lazy by adding a <literal>~</literal> in
+ front of the field.</para>
+
+ <para>When the user writes</para>
+
+ <programlisting>
+ data T = C a
+ data T' = C' ~a
+ </programlisting>
+
+ <para>we interpret it as if she had written</para>
+
+ <programlisting>
+ data T = C !a
+ data T' = C' a
+ </programlisting>
+
+ <para>The extension only affects definitions in this module.</para>
+ </sect2>
+
+</sect1>
+
<!-- Emacs stuff:
;;; Local Variables: ***
;;; sgml-parent-document: ("users_guide.xml" "book" "chapter" "sect1") ***
;;; ispell-local-dictionary: "british" ***
;;; End: ***
-->
-
diff --git a/testsuite/tests/deSugar/should_run/DsStrictData.hs b/testsuite/tests/deSugar/should_run/DsStrictData.hs
new file mode 100644
index 0000000000..f1898a5f6a
--- /dev/null
+++ b/testsuite/tests/deSugar/should_run/DsStrictData.hs
@@ -0,0 +1,48 @@
+{-# LANGUAGE ScopedTypeVariables, StrictData, GADTs #-}
+
+-- | Tests the StrictData LANGUAGE pragma.
+module Main where
+
+import qualified Control.Exception as E
+import System.IO.Unsafe (unsafePerformIO)
+
+data Strict a = S a
+data Strict2 b = S2 !b
+data Strict3 c where
+ S3 :: c -> Strict3 c
+
+data UStrict = US {-# UNPACK #-} Int
+
+data Lazy d = L ~d
+data Lazy2 e where
+ L2 :: ~e -> Lazy2 e
+
+main :: IO ()
+main =
+ do print (isBottom (S bottom))
+ print (isBottom (S2 bottom))
+ print (isBottom (US bottom))
+ print (isBottom (S3 bottom))
+ putStrLn ""
+ print (not (isBottom (L bottom)))
+ print (not (isBottom (L2 bottom)))
+ print (not (isBottom (Just bottom))) -- sanity check
+
+------------------------------------------------------------------------
+-- Support for testing for bottom
+
+bottom :: a
+bottom = error "_|_"
+
+isBottom :: a -> Bool
+isBottom f = unsafePerformIO $
+ (E.evaluate f >> return False) `E.catches`
+ [ E.Handler (\(_ :: E.ArrayException) -> return True)
+ , E.Handler (\(_ :: E.ErrorCall) -> return True)
+ , E.Handler (\(_ :: E.NoMethodError) -> return True)
+ , E.Handler (\(_ :: E.NonTermination) -> return True)
+ , E.Handler (\(_ :: E.PatternMatchFail) -> return True)
+ , E.Handler (\(_ :: E.RecConError) -> return True)
+ , E.Handler (\(_ :: E.RecSelError) -> return True)
+ , E.Handler (\(_ :: E.RecUpdError) -> return True)
+ ]
diff --git a/testsuite/tests/deSugar/should_run/DsStrictData.stdout b/testsuite/tests/deSugar/should_run/DsStrictData.stdout
new file mode 100644
index 0000000000..b34f35dcee
--- /dev/null
+++ b/testsuite/tests/deSugar/should_run/DsStrictData.stdout
@@ -0,0 +1,8 @@
+True
+True
+True
+True
+
+True
+True
+True
diff --git a/testsuite/tests/deSugar/should_run/all.T b/testsuite/tests/deSugar/should_run/all.T
index 57878161a3..228b90dd0f 100644
--- a/testsuite/tests/deSugar/should_run/all.T
+++ b/testsuite/tests/deSugar/should_run/all.T
@@ -47,3 +47,4 @@ test('DsStaticPointers',
compile_and_run, [''])
test('T8952', normal, compile_and_run, [''])
test('T9844', normal, compile_and_run, [''])
+test('DsStrictData', normal, compile_and_run, [''])
diff --git a/testsuite/tests/driver/T4437.hs b/testsuite/tests/driver/T4437.hs
index dde6da7b16..3c6de35402 100644
--- a/testsuite/tests/driver/T4437.hs
+++ b/testsuite/tests/driver/T4437.hs
@@ -33,7 +33,8 @@ expectedGhcOnlyExtensions :: [String]
expectedGhcOnlyExtensions = ["RelaxedLayout",
"AlternativeLayoutRule",
"AlternativeLayoutRuleTransitional",
- "StaticPointers"]
+ "StaticPointers",
+ "StrictData"]
expectedCabalOnlyExtensions :: [String]
expectedCabalOnlyExtensions = ["Generics",
@@ -47,4 +48,3 @@ expectedCabalOnlyExtensions = ["Generics",
"Safe",
"Unsafe",
"Trustworthy"]
-
diff --git a/utils/haddock b/utils/haddock
-Subproject 553c719236972f3a1d445146352ec94614979b6
+Subproject 5eb0785cde60997f072c3bdfefaf8c389c96d42