summaryrefslogtreecommitdiff
path: root/compiler/hsSyn/HsBinds.hs
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2017-07-31 10:49:16 +0100
committerSimon Peyton Jones <simonpj@microsoft.com>2017-07-31 13:36:49 +0100
commit46368868dc85fc7f0c95fe88af892ad850ed7bc6 (patch)
tree4e290b5580fa55e445712f5a0653bcb3c229c30b /compiler/hsSyn/HsBinds.hs
parent2535a6716202253df74d8190b028f85cc6d21b72 (diff)
downloadhaskell-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.hs81
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 })