- ; return (sel_binds ++ rest) }
-
-{- Note [Rules and inlining]
- ~~~~~~~~~~~~~~~~~~~~~~~~~
- Common special case: no type or dictionary abstraction
- This is a bit less trivial than you might suppose
- The naive way woudl be to desguar to something like
- f_lcl = ...f_lcl... -- The "binds" from AbsBinds
- M.f = f_lcl -- Generated from "exports"
- But we don't want that, because if M.f isn't exported,
- it'll be inlined unconditionally at every call site (its rhs is
- trivial). That would be ok unless it has RULES, which would
- thereby be completely lost. Bad, bad, bad.
-
- Instead we want to generate
- M.f = ...f_lcl...
- f_lcl = M.f
- Now all is cool. The RULES are attached to M.f (by SimplCore),
- and f_lcl is rapidly inlined away.
-
- This does not happen in the same way to polymorphic binds,
- because they desugar to
- M.f = /\a. let f_lcl = ...f_lcl... in f_lcl
- Although I'm a bit worried about whether full laziness might
- float the f_lcl binding out and then inline M.f at its call site -}
-
-dsHsBind auto_scc rest (AbsBinds [] [] exports binds)
- = do { core_prs <- ds_lhs_binds NoSccs binds
- ; let env = mkABEnv exports
- ar_env = mkArityEnv binds
- do_one (lcl_id, rhs)
- | Just (_, gbl_id, _, spec_prags) <- lookupVarEnv env lcl_id
- = WARN( not (null spec_prags), ppr gbl_id $$ ppr spec_prags ) -- Not overloaded
- makeCorePair gbl_id (lookupArity ar_env lcl_id)
- (addAutoScc auto_scc gbl_id rhs)
-
- | otherwise = (lcl_id, rhs)
-
- locals' = [(lcl_id, Var gbl_id) | (_, gbl_id, lcl_id, _) <- exports]
- -- Note [Rules and inlining]
- ; return (map do_one core_prs ++ locals' ++ rest) }
- -- No Rec needed here (contrast the other AbsBinds cases)
- -- because we can rely on the enclosing dsBind to wrap in Rec
-
-
-{- Note [Abstracting over tyvars only]
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- When abstracting over type variable only (not dictionaries), we don't really need to
- built a tuple and select from it, as we do in the general case. Instead we can take
-
- AbsBinds [a,b] [ ([a,b], fg, fl, _),
- ([b], gg, gl, _) ]
- { fl = e1
- gl = e2
- h = e3 }
-
- and desugar it to
-
- fg = /\ab. let B in e1
- gg = /\b. let a = () in let B in S(e2)
- h = /\ab. let B in e3
-
- where B is the *non-recursive* binding
- fl = fg a b
- gl = gg b
- h = h a b -- See (b); note shadowing!
-
- Notice (a) g has a different number of type variables to f, so we must
- use the mkArbitraryType thing to fill in the gaps.
- We use a type-let to do that.
-
- (b) The local variable h isn't in the exports, and rather than
- clone a fresh copy we simply replace h by (h a b), where
- the two h's have different types! Shadowing happens here,
- which looks confusing but works fine.
-
- (c) The result is *still* quadratic-sized if there are a lot of
- small bindings. So if there are more than some small
- number (10), we filter the binding set B by the free
- variables of the particular RHS. Tiresome.