diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2017-07-31 10:49:16 +0100 |
---|---|---|
committer | Simon Peyton Jones <simonpj@microsoft.com> | 2017-07-31 13:36:49 +0100 |
commit | 46368868dc85fc7f0c95fe88af892ad850ed7bc6 (patch) | |
tree | 4e290b5580fa55e445712f5a0653bcb3c229c30b /compiler/hsSyn/HsBinds.hs | |
parent | 2535a6716202253df74d8190b028f85cc6d21b72 (diff) | |
download | haskell-46368868dc85fc7f0c95fe88af892ad850ed7bc6.tar.gz |
Improve the desugaring of -XStrict
Trac #14035 showed that -XStrict was generating some TERRIBLE
desugarings, espcially for bindings with INLINE pragmas. Reason: with
-XStrict, all AbsBinds (even for non-recursive functions) went via the
general-case deguaring for AbsBinds, namely "generate a tuple and
select from it", even though in this case there was only one variable
in the tuple. And that in turn interacts terribly badly with INLINE
pragmas.
This patch cleans things up:
* I killed off AbsBindsSig completely, in favour of a boolean flag
abs_sig in AbsBinds. See Note [The abs_sig field of AbsBinds]
This allowed me to delete lots of code; and instance-method
declarations can enjoy the benefits too. (They could have
before, but no one had changed them to use AbsBindsSig.)
* I refactored all the AbsBinds handling in DsBinds into a new
function DsBinds.dsAbsBinds. This allowed me to handle the
strict case uniformly
Diffstat (limited to 'compiler/hsSyn/HsBinds.hs')
-rw-r--r-- | compiler/hsSyn/HsBinds.hs | 81 |
1 files changed, 50 insertions, 31 deletions
diff --git a/compiler/hsSyn/HsBinds.hs b/compiler/hsSyn/HsBinds.hs index d766ab2c13..a8efa7206f 100644 --- a/compiler/hsSyn/HsBinds.hs +++ b/compiler/hsSyn/HsBinds.hs @@ -269,22 +269,9 @@ data HsBindLR idL idR abs_ev_binds :: [TcEvBinds], -- | Typechecked user bindings - abs_binds :: LHsBinds idL - } - - -- | Abstraction Bindings Signature - | AbsBindsSig { -- Simpler form of AbsBinds, used with a type sig - -- in tcPolyCheck. Produces simpler desugaring and - -- is necessary to avoid #11405, comment:3. - abs_tvs :: [TyVar], - abs_ev_vars :: [EvVar], - - abs_sig_export :: IdP idL, -- like abe_poly - abs_sig_prags :: TcSpecPrags, + abs_binds :: LHsBinds idL, - abs_sig_ev_bind :: TcEvBinds, -- no list needed here - abs_sig_bind :: LHsBind idL -- always only one, and it's always a - -- FunBind + abs_sig :: Bool -- See Note [The abs_sig field of AbsBinds] } -- | Patterns Synonym Binding @@ -312,7 +299,7 @@ deriving instance (DataId idL, DataId idR) => Data (HsBindLR idL idR) -- | Abtraction Bindings Export data ABExport p - = ABE { abe_poly :: IdP p -- ^ Any INLINE pragmas is attached to this Id + = ABE { abe_poly :: IdP p -- ^ Any INLINE pragma is attached to this Id , abe_mono :: IdP p , abe_wrap :: HsWrapper -- ^ See Note [ABExport wrapper] -- Shape: (forall abs_tvs. abs_ev_vars => abe_mono) ~ abe_poly @@ -481,6 +468,53 @@ bindings only when lacks a user type signature * The group forms a strongly connected component + +Note [The abs_sig field of AbsBinds] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The abs_sig field supports a couple of special cases for bindings. +Consider + + x :: Num a => (# a, a #) + x = (# 3, 4 #) + +The general desugaring for AbsBinds would give + + x = /\a. \ ($dNum :: Num a) -> + letrec xm = (# fromInteger $dNum 3, fromInteger $dNum 4 #) in + xm + +But that has an illegal let-binding for an unboxed tuple. In this +case we'd prefer to generate the (more direct) + + x = /\ a. \ ($dNum :: Num a) -> + (# fromInteger $dNum 3, fromInteger $dNum 4 #) + +A similar thing happens with representation-polymorphic defns +(Trac #11405): + + undef :: forall (r :: RuntimeRep) (a :: TYPE r). HasCallStack => a + undef = error "undef" + +Again, the vanilla desugaring gives a local let-binding for a +representation-polymorphic (undefm :: a), which is illegal. But +again we can desugar without a let: + + undef = /\ a. \ (d:HasCallStack) -> error a d "undef" + +The abs_sig field supports this direct desugaring, with no local +let-bining. When abs_sig = True + + * the abs_binds is single FunBind + + * the abs_exports is a singleton + + * we have a complete type sig for binder + and hence the abs_binds is non-recursive + (it binds the mono_id but refers to the poly_id + +These properties are exploited in DsBinds.dsAbsBinds to +generate code without a let-binding. + Note [ABExport wrapper] ~~~~~~~~~~~~~~~~~~~~~~~ Consider @@ -662,21 +696,6 @@ ppr_monobind (AbsBinds { abs_tvs = tyvars, abs_ev_vars = dictvars , text "Evidence:" <+> ppr ev_binds ] else pprLHsBinds val_binds -ppr_monobind (AbsBindsSig { abs_tvs = tyvars - , abs_ev_vars = dictvars - , abs_sig_export = poly_id - , abs_sig_ev_bind = ev_bind - , abs_sig_bind = bind }) - = sdocWithDynFlags $ \ dflags -> - if gopt Opt_PrintTypecheckerElaboration dflags then - hang (text "AbsBindsSig" <+> brackets (interpp'SP tyvars) - <+> brackets (interpp'SP dictvars)) - 2 $ braces $ vcat - [ text "Exported type:" <+> pprBndr LetBind poly_id - , text "Bind:" <+> ppr bind - , text "Evidence:" <+> ppr ev_bind ] - else - ppr bind instance (OutputableBndrId p) => Outputable (ABExport p) where ppr (ABE { abe_wrap = wrap, abe_poly = gbl, abe_mono = lcl, abe_prags = prags }) |