Commit d3f002cc authored by Simon Peyton Jones's avatar Simon Peyton Jones

Fix over-eager unpacking in isUnpackableType

This bug meant that we tried to unpack Link in

  data Link a = MkLink !(Link a)

when -funbox-small-strict-fields was on.  See Trac #8221.
parent 1fb558d1
...@@ -695,8 +695,7 @@ dataConArgUnpack arg_ty ...@@ -695,8 +695,7 @@ dataConArgUnpack arg_ty
-- An interface file specified Unpacked, but we couldn't unpack it -- An interface file specified Unpacked, but we couldn't unpack it
isUnpackableType :: FamInstEnvs -> Type -> Bool isUnpackableType :: FamInstEnvs -> Type -> Bool
-- True if we can unpack the UNPACK fields of the constructor -- True if we can unpack the UNPACK the argument type
-- without involving the NameSet tycons
-- See Note [Recursive unboxing] -- See Note [Recursive unboxing]
-- We look "deeply" inside rather than relying on the DataCons -- We look "deeply" inside rather than relying on the DataCons
-- we encounter on the way, because otherwise we might well -- we encounter on the way, because otherwise we might well
...@@ -730,9 +729,11 @@ isUnpackableType fam_envs ty ...@@ -730,9 +729,11 @@ isUnpackableType fam_envs ty
-- NB: dataConStrictMarks gives the *user* request; -- NB: dataConStrictMarks gives the *user* request;
-- We'd get a black hole if we used dataConRepBangs -- We'd get a black hole if we used dataConRepBangs
attempt_unpack (HsUnpack {}) = True attempt_unpack (HsUnpack {}) = True
attempt_unpack (HsUserBang (Just unpk) _) = unpk attempt_unpack (HsUserBang (Just unpk) bang) = bang && unpk
attempt_unpack _ = False attempt_unpack (HsUserBang Nothing bang) = bang -- Be conservative
attempt_unpack HsStrict = False
attempt_unpack HsNoBang = False
\end{code} \end{code}
Note [Unpack one-wide fields] Note [Unpack one-wide fields]
...@@ -761,14 +762,26 @@ Here we can represent T with an Int#. ...@@ -761,14 +762,26 @@ Here we can represent T with an Int#.
Note [Recursive unboxing] Note [Recursive unboxing]
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~
Be careful not to try to unbox this! Consider
data T = MkT {-# UNPACK #-} !T Int
Reason: consider
data R = MkR {-# UNPACK #-} !S Int data R = MkR {-# UNPACK #-} !S Int
data S = MkS {-# UNPACK #-} !Int data S = MkS {-# UNPACK #-} !Int
The representation arguments of MkR are the *representation* arguments The representation arguments of MkR are the *representation* arguments
of S (plus Int); the rep args of MkS are Int#. This is obviously no of S (plus Int); the rep args of MkS are Int#. This is all fine.
good for T, because then we'd get an infinite number of arguments.
But be careful not to try to unbox this!
data T = MkT {-# UNPACK #-} !T Int
Because then we'd get an infinite number of arguments.
Here is a more complicated case:
data S = MkS {-# UNPACK #-} !T Int
data T = MkT {-# UNPACK #-} !S Int
Each of S and T must decide independendently whether to unpack
and they had better not both say yes. So they must both say no.
Also behave conservatively when there is no UNPACK pragma
data T = MkS !T Int
with -funbox-strict-fields or -funbox-small-strict-fields
we need to behave as if there was an UNPACK pragma there.
But it's the *argument* type that matters. This is fine: But it's the *argument* type that matters. This is fine:
data S = MkS S !Int data S = MkS S !Int
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment