summaryrefslogtreecommitdiff
path: root/compiler/rename/RnSplice.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rename/RnSplice.hs')
-rw-r--r--compiler/rename/RnSplice.hs563
1 files changed, 563 insertions, 0 deletions
diff --git a/compiler/rename/RnSplice.hs b/compiler/rename/RnSplice.hs
new file mode 100644
index 0000000000..e147e6a883
--- /dev/null
+++ b/compiler/rename/RnSplice.hs
@@ -0,0 +1,563 @@
+{-# LANGUAGE CPP #-}
+
+module RnSplice (
+ rnTopSpliceDecls,
+ rnSpliceType, rnSpliceExpr, rnSplicePat, rnSpliceDecl,
+ rnBracket,
+ checkThLocalName
+ ) where
+
+
+import Name
+import NameSet
+import HsSyn
+import RdrName
+import TcRnMonad
+import Kind
+
+#ifdef GHCI
+import Control.Monad ( unless, when )
+import DynFlags
+import DsMeta ( decsQTyConName, expQTyConName, patQTyConName, typeQTyConName )
+import LoadIface ( loadInterfaceForName )
+import Module
+import RnEnv
+import RnPat ( rnPat )
+import RnSource ( rnSrcDecls, findSplice )
+import RnTypes ( rnLHsType )
+import SrcLoc
+import TcEnv ( checkWellStaged, tcMetaTy )
+import Outputable
+import BasicTypes ( TopLevelFlag, isTopLevel )
+import FastString
+import Hooks
+
+import {-# SOURCE #-} RnExpr ( rnLExpr )
+import {-# SOURCE #-} TcExpr ( tcMonoExpr )
+import {-# SOURCE #-} TcSplice ( runMetaD, runMetaE, runMetaP, runMetaT, tcTopSpliceExpr )
+#endif
+
+#ifndef GHCI
+rnBracket :: HsExpr RdrName -> HsBracket RdrName -> RnM (HsExpr Name, FreeVars)
+rnBracket e _ = failTH e "Template Haskell bracket"
+
+rnTopSpliceDecls :: HsSplice RdrName -> RnM ([LHsDecl RdrName], FreeVars)
+rnTopSpliceDecls e = failTH e "Template Haskell top splice"
+
+rnSpliceType :: HsSplice RdrName -> PostTc Name Kind
+ -> RnM (HsType Name, FreeVars)
+rnSpliceType e _ = failTH e "Template Haskell type splice"
+
+rnSpliceExpr :: Bool -> HsSplice RdrName -> RnM (HsExpr Name, FreeVars)
+rnSpliceExpr _ e = failTH e "Template Haskell splice"
+
+rnSplicePat :: HsSplice RdrName -> RnM (Either (Pat RdrName) (Pat Name), FreeVars)
+rnSplicePat e = failTH e "Template Haskell pattern splice"
+
+rnSpliceDecl :: SpliceDecl RdrName -> RnM (SpliceDecl Name, FreeVars)
+rnSpliceDecl e = failTH e "Template Haskell declaration splice"
+#else
+
+{-
+*********************************************************
+* *
+ Splices
+* *
+*********************************************************
+
+Note [Free variables of typed splices]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider renaming this:
+ f = ...
+ h = ...$(thing "f")...
+
+where the splice is a *typed* splice. The splice can expand into
+literally anything, so when we do dependency analysis we must assume
+that it might mention 'f'. So we simply treat all locally-defined
+names as mentioned by any splice. This is terribly brutal, but I
+don't see what else to do. For example, it'll mean that every
+locally-defined thing will appear to be used, so no unused-binding
+warnings. But if we miss the dependency, then we might typecheck 'h'
+before 'f', and that will crash the type checker because 'f' isn't in
+scope.
+
+Currently, I'm not treating a splice as also mentioning every import,
+which is a bit inconsistent -- but there are a lot of them. We might
+thereby get some bogus unused-import warnings, but we won't crash the
+type checker. Not very satisfactory really.
+
+Note [Renamer errors]
+~~~~~~~~~~~~~~~~~~~~~
+It's important to wrap renamer calls in checkNoErrs, because the
+renamer does not fail for out of scope variables etc. Instead it
+returns a bogus term/type, so that it can report more than one error.
+We don't want the type checker to see these bogus unbound variables.
+-}
+
+rnSpliceGen :: Bool -- Typed splice?
+ -> (HsSplice Name -> RnM (a, FreeVars)) -- Outside brackets, run splice
+ -> (HsSplice Name -> (PendingRnSplice, a)) -- Inside brackets, make it pending
+ -> HsSplice RdrName
+ -> RnM (a, FreeVars)
+rnSpliceGen is_typed_splice run_splice pend_splice splice@(HsSplice _ expr)
+ = addErrCtxt (spliceCtxt (HsSpliceE is_typed_splice splice)) $
+ setSrcSpan (getLoc expr) $ do
+ { stage <- getStage
+ ; case stage of
+ Brack pop_stage RnPendingTyped
+ -> do { checkTc is_typed_splice illegalUntypedSplice
+ ; (splice', fvs) <- setStage pop_stage $
+ rnSplice splice
+ ; let (_pending_splice, result) = pend_splice splice'
+ ; return (result, fvs) }
+
+ Brack pop_stage (RnPendingUntyped ps_var)
+ -> do { checkTc (not is_typed_splice) illegalTypedSplice
+ ; (splice', fvs) <- setStage pop_stage $
+ rnSplice splice
+ ; let (pending_splice, result) = pend_splice splice'
+ ; ps <- readMutVar ps_var
+ ; writeMutVar ps_var (pending_splice : ps)
+ ; return (result, fvs) }
+
+ _ -> do { (splice', fvs1) <- setStage (Splice is_typed_splice) $
+ rnSplice splice
+
+ ; (result, fvs2) <- run_splice splice'
+ ; return (result, fvs1 `plusFV` fvs2) } }
+
+---------------------
+rnSplice :: HsSplice RdrName -> RnM (HsSplice Name, FreeVars)
+-- Not exported...used for all
+rnSplice (HsSplice splice_name expr)
+ = do { checkTH expr "Template Haskell splice"
+ ; loc <- getSrcSpanM
+ ; n' <- newLocalBndrRn (L loc splice_name)
+ ; (expr', fvs) <- rnLExpr expr
+ ; return (HsSplice n' expr', fvs) }
+
+---------------------
+rnSpliceExpr :: Bool -> HsSplice RdrName -> RnM (HsExpr Name, FreeVars)
+rnSpliceExpr is_typed splice
+ = rnSpliceGen is_typed run_expr_splice pend_expr_splice splice
+ where
+ pend_expr_splice :: HsSplice Name -> (PendingRnSplice, HsExpr Name)
+ pend_expr_splice rn_splice@(HsSplice n e)
+ = (PendingRnExpSplice (PendSplice n e), HsSpliceE is_typed rn_splice)
+
+ run_expr_splice :: HsSplice Name -> RnM (HsExpr Name, FreeVars)
+ run_expr_splice rn_splice@(HsSplice _ expr')
+ | is_typed -- Run it later, in the type checker
+ = do { -- Ugh! See Note [Splices] above
+ lcl_rdr <- getLocalRdrEnv
+ ; gbl_rdr <- getGlobalRdrEnv
+ ; let gbl_names = mkNameSet [gre_name gre | gre <- globalRdrEnvElts gbl_rdr
+ , isLocalGRE gre]
+ lcl_names = mkNameSet (localRdrEnvElts lcl_rdr)
+
+ ; return (HsSpliceE is_typed rn_splice, lcl_names `plusFV` gbl_names) }
+
+ | otherwise -- Run it here
+ = do { expr <- getHooked runRnSpliceHook return >>= ($ expr')
+
+ -- The splice must have type ExpQ
+ ; meta_exp_ty <- tcMetaTy expQTyConName
+
+ -- Typecheck the expression
+ ; zonked_q_expr <- tcTopSpliceExpr False $
+ tcMonoExpr expr meta_exp_ty
+
+ -- Run the expression
+ ; expr2 <- runMetaE zonked_q_expr
+ ; showSplice "expression" expr (ppr expr2)
+
+ ; (lexpr3, fvs) <- checkNoErrs $
+ rnLExpr expr2
+ ; return (unLoc lexpr3, fvs) }
+
+----------------------
+rnSpliceType :: HsSplice RdrName -> PostTc Name Kind
+ -> RnM (HsType Name, FreeVars)
+rnSpliceType splice k
+ = rnSpliceGen False run_type_splice pend_type_splice splice
+ where
+ pend_type_splice rn_splice@(HsSplice n e)
+ = (PendingRnTypeSplice (PendSplice n e), HsSpliceTy rn_splice k)
+
+ run_type_splice (HsSplice _ expr')
+ = do { expr <- getHooked runRnSpliceHook return >>= ($ expr')
+
+ ; meta_exp_ty <- tcMetaTy typeQTyConName
+
+ -- Typecheck the expression
+ ; zonked_q_expr <- tcTopSpliceExpr False $
+ tcMonoExpr expr meta_exp_ty
+
+ -- Run the expression
+ ; hs_ty2 <- runMetaT zonked_q_expr
+ ; showSplice "type" expr (ppr hs_ty2)
+
+ ; (hs_ty3, fvs) <- do { let doc = SpliceTypeCtx hs_ty2
+ ; checkNoErrs $ rnLHsType doc hs_ty2
+ -- checkNoErrs: see Note [Renamer errors]
+ }
+ ; return (unLoc hs_ty3, fvs) }
+
+{-
+Note [rnSplicePat]
+~~~~~~~~~~~~~~~~~~
+Renaming a pattern splice is a bit tricky, because we need the variables
+bound in the pattern to be in scope in the RHS of the pattern. This scope
+management is effectively done by using continuation-passing style in
+RnPat, through the CpsRn monad. We don't wish to be in that monad here
+(it would create import cycles and generally conflict with renaming other
+splices), so we really want to return a (Pat RdrName) -- the result of
+running the splice -- which can then be further renamed in RnPat, in
+the CpsRn monad.
+
+The problem is that if we're renaming a splice within a bracket, we
+*don't* want to run the splice now. We really do just want to rename
+it to an HsSplice Name. Of course, then we can't know what variables
+are bound within the splice, so pattern splices within brackets aren't
+all that useful.
+
+In any case, when we're done in rnSplicePat, we'll either have a
+Pat RdrName (the result of running a top-level splice) or a Pat Name
+(the renamed nested splice). Thus, the awkward return type of
+rnSplicePat.
+-}
+
+-- | Rename a splice pattern. See Note [rnSplicePat]
+rnSplicePat :: HsSplice RdrName -> RnM ( Either (Pat RdrName) (Pat Name)
+ , FreeVars)
+rnSplicePat splice
+ = rnSpliceGen False run_pat_splice pend_pat_splice splice
+ where
+ pend_pat_splice rn_splice@(HsSplice n e)
+ = (PendingRnPatSplice (PendSplice n e), Right $ SplicePat rn_splice)
+
+ run_pat_splice (HsSplice _ expr')
+ = do { expr <- getHooked runRnSpliceHook return >>= ($ expr')
+
+ ; meta_exp_ty <- tcMetaTy patQTyConName
+
+ -- Typecheck the expression
+ ; zonked_q_expr <- tcTopSpliceExpr False $
+ tcMonoExpr expr meta_exp_ty
+
+ -- Run the expression
+ ; pat <- runMetaP zonked_q_expr
+ ; showSplice "pattern" expr (ppr pat)
+
+ ; return (Left $ unLoc pat, emptyFVs) }
+
+----------------------
+rnSpliceDecl :: SpliceDecl RdrName -> RnM (SpliceDecl Name, FreeVars)
+rnSpliceDecl (SpliceDecl (L loc splice) flg)
+ = rnSpliceGen False run_decl_splice pend_decl_splice splice
+ where
+ pend_decl_splice rn_splice@(HsSplice n e)
+ = (PendingRnDeclSplice (PendSplice n e), SpliceDecl(L loc rn_splice) flg)
+
+ run_decl_splice rn_splice = pprPanic "rnSpliceDecl" (ppr rn_splice)
+
+rnTopSpliceDecls :: HsSplice RdrName -> RnM ([LHsDecl RdrName], FreeVars)
+-- Declaration splice at the very top level of the module
+rnTopSpliceDecls (HsSplice _ expr'')
+ = do { (expr, fvs) <- setStage (Splice False) $
+ rnLExpr expr''
+
+ ; expr' <- getHooked runRnSpliceHook return >>= ($ expr)
+
+ ; list_q <- tcMetaTy decsQTyConName -- Q [Dec]
+ ; zonked_q_expr <- tcTopSpliceExpr False (tcMonoExpr expr' list_q)
+
+ -- Run the expression
+ ; decls <- runMetaD zonked_q_expr
+ ; showSplice "declarations" expr'
+ (ppr (getLoc expr) $$ (vcat (map ppr decls)))
+
+ ; return (decls,fvs) }
+
+{-
+************************************************************************
+* *
+ Template Haskell brackets
+* *
+************************************************************************
+-}
+
+rnBracket :: HsExpr RdrName -> HsBracket RdrName -> RnM (HsExpr Name, FreeVars)
+rnBracket e br_body
+ = addErrCtxt (quotationCtxtDoc br_body) $
+ do { -- Check that Template Haskell is enabled and available
+ thEnabled <- xoptM Opt_TemplateHaskell
+ ; unless thEnabled $
+ failWith ( vcat [ ptext (sLit "Syntax error on") <+> ppr e
+ , ptext (sLit "Perhaps you intended to use TemplateHaskell") ] )
+ ; checkTH e "Template Haskell bracket"
+
+ -- Check for nested brackets
+ ; cur_stage <- getStage
+ ; case cur_stage of
+ { Splice True -> checkTc (isTypedBracket br_body) illegalUntypedBracket
+ ; Splice False -> checkTc (not (isTypedBracket br_body)) illegalTypedBracket
+ ; Comp -> return ()
+ ; Brack {} -> failWithTc illegalBracket
+ }
+
+ -- Brackets are desugared to code that mentions the TH package
+ ; recordThUse
+
+ ; case isTypedBracket br_body of
+ True -> do { (body', fvs_e) <- setStage (Brack cur_stage RnPendingTyped) $
+ rn_bracket cur_stage br_body
+ ; return (HsBracket body', fvs_e) }
+
+ False -> do { ps_var <- newMutVar []
+ ; (body', fvs_e) <- setStage (Brack cur_stage (RnPendingUntyped ps_var)) $
+ rn_bracket cur_stage br_body
+ ; pendings <- readMutVar ps_var
+ ; return (HsRnBracketOut body' pendings, fvs_e) }
+ }
+
+rn_bracket :: ThStage -> HsBracket RdrName -> RnM (HsBracket Name, FreeVars)
+rn_bracket outer_stage br@(VarBr flg rdr_name)
+ = do { name <- lookupOccRn rdr_name
+ ; this_mod <- getModule
+
+ ; case flg of
+ { -- Type variables can be quoted in TH. See #5721.
+ False -> return ()
+ ; True | nameIsLocalOrFrom this_mod name ->
+ do { mb_bind_lvl <- lookupLocalOccThLvl_maybe name
+ ; case mb_bind_lvl of
+ { Nothing -> return () -- Can happen for data constructors,
+ -- but nothing needs to be done for them
+
+ ; Just (top_lvl, bind_lvl) -- See Note [Quoting names]
+ | isTopLevel top_lvl
+ -> when (isExternalName name) (keepAlive name)
+ | otherwise
+ -> do { traceRn (text "rn_bracket VarBr" <+> ppr name <+> ppr bind_lvl <+> ppr outer_stage)
+ ; checkTc (thLevel outer_stage + 1 == bind_lvl)
+ (quotedNameStageErr br) }
+ }
+ }
+ ; True | otherwise -> -- Imported thing
+ discardResult (loadInterfaceForName msg name)
+ -- Reason for loadInterface: deprecation checking
+ -- assumes that the home interface is loaded, and
+ -- this is the only way that is going to happen
+ }
+ ; return (VarBr flg name, unitFV name) }
+ where
+ msg = ptext (sLit "Need interface for Template Haskell quoted Name")
+
+rn_bracket _ (ExpBr e) = do { (e', fvs) <- rnLExpr e
+ ; return (ExpBr e', fvs) }
+
+rn_bracket _ (PatBr p) = rnPat ThPatQuote p $ \ p' -> return (PatBr p', emptyFVs)
+
+rn_bracket _ (TypBr t) = do { (t', fvs) <- rnLHsType TypBrCtx t
+ ; return (TypBr t', fvs) }
+
+rn_bracket _ (DecBrL decls)
+ = do { group <- groupDecls decls
+ ; gbl_env <- getGblEnv
+ ; let new_gbl_env = gbl_env { tcg_dus = emptyDUs }
+ -- The emptyDUs is so that we just collect uses for this
+ -- group alone in the call to rnSrcDecls below
+ ; (tcg_env, group') <- setGblEnv new_gbl_env $
+ rnSrcDecls [] group
+ -- The empty list is for extra dependencies coming from .hs-boot files
+ -- See Note [Extra dependencies from .hs-boot files] in RnSource
+
+ -- Discard the tcg_env; it contains only extra info about fixity
+ ; traceRn (text "rn_bracket dec" <+> (ppr (tcg_dus tcg_env) $$
+ ppr (duUses (tcg_dus tcg_env))))
+ ; return (DecBrG group', duUses (tcg_dus tcg_env)) }
+ where
+ groupDecls :: [LHsDecl RdrName] -> RnM (HsGroup RdrName)
+ groupDecls decls
+ = do { (group, mb_splice) <- findSplice decls
+ ; case mb_splice of
+ { Nothing -> return group
+ ; Just (splice, rest) ->
+ do { group' <- groupDecls rest
+ ; let group'' = appendGroups group group'
+ ; return group'' { hs_splcds = noLoc splice : hs_splcds group' }
+ }
+ }}
+
+rn_bracket _ (DecBrG _) = panic "rn_bracket: unexpected DecBrG"
+
+rn_bracket _ (TExpBr e) = do { (e', fvs) <- rnLExpr e
+ ; return (TExpBr e', fvs) }
+
+spliceCtxt :: HsExpr RdrName -> SDoc
+spliceCtxt expr= hang (ptext (sLit "In the splice:")) 2 (ppr expr)
+
+showSplice :: String -> LHsExpr Name -> SDoc -> TcM ()
+-- Note that 'before' is *renamed* but not *typechecked*
+-- Reason (a) less typechecking crap
+-- (b) data constructors after type checking have been
+-- changed to their *wrappers*, and that makes them
+-- print always fully qualified
+showSplice what before after
+ = do { loc <- getSrcSpanM
+ ; traceSplice (vcat [ppr loc <> colon <+> text "Splicing" <+> text what,
+ nest 2 (sep [nest 2 (ppr before),
+ text "======>",
+ nest 2 after])]) }
+
+illegalBracket :: SDoc
+illegalBracket = ptext (sLit "Template Haskell brackets cannot be nested (without intervening splices)")
+
+illegalTypedBracket :: SDoc
+illegalTypedBracket = ptext (sLit "Typed brackets may only appear in typed slices.")
+
+illegalUntypedBracket :: SDoc
+illegalUntypedBracket = ptext (sLit "Untyped brackets may only appear in untyped slices.")
+
+illegalTypedSplice :: SDoc
+illegalTypedSplice = ptext (sLit "Typed splices may not appear in untyped brackets")
+
+illegalUntypedSplice :: SDoc
+illegalUntypedSplice = ptext (sLit "Untyped splices may not appear in typed brackets")
+
+quotedNameStageErr :: HsBracket RdrName -> SDoc
+quotedNameStageErr br
+ = sep [ ptext (sLit "Stage error: the non-top-level quoted name") <+> ppr br
+ , ptext (sLit "must be used at the same stage at which is is bound")]
+
+quotationCtxtDoc :: HsBracket RdrName -> SDoc
+quotationCtxtDoc br_body
+ = hang (ptext (sLit "In the Template Haskell quotation"))
+ 2 (ppr br_body)
+
+-- spliceResultDoc :: OutputableBndr id => LHsExpr id -> SDoc
+-- spliceResultDoc expr
+-- = vcat [ hang (ptext (sLit "In the splice:"))
+-- 2 (char '$' <> pprParendExpr expr)
+-- , ptext (sLit "To see what the splice expanded to, use -ddump-splices") ]
+#endif
+
+checkThLocalName :: Name -> RnM ()
+#ifndef GHCI /* GHCI and TH is off */
+--------------------------------------
+-- Check for cross-stage lifting
+checkThLocalName _name
+ = return ()
+
+#else /* GHCI and TH is on */
+checkThLocalName name
+ = do { traceRn (text "checkThLocalName" <+> ppr name)
+ ; mb_local_use <- getStageAndBindLevel name
+ ; case mb_local_use of {
+ Nothing -> return () ; -- Not a locally-bound thing
+ Just (top_lvl, bind_lvl, use_stage) ->
+ do { let use_lvl = thLevel use_stage
+ ; checkWellStaged (quotes (ppr name)) bind_lvl use_lvl
+ ; traceRn (text "checkThLocalName" <+> ppr name <+> ppr bind_lvl <+> ppr use_stage <+> ppr use_lvl)
+ ; when (use_lvl > bind_lvl) $
+ checkCrossStageLifting top_lvl name use_stage } } }
+
+--------------------------------------
+checkCrossStageLifting :: TopLevelFlag -> Name -> ThStage -> TcM ()
+-- We are inside brackets, and (use_lvl > bind_lvl)
+-- Now we must check whether there's a cross-stage lift to do
+-- Examples \x -> [| x |]
+-- [| map |]
+
+checkCrossStageLifting top_lvl name (Brack _ (RnPendingUntyped ps_var))
+ | isTopLevel top_lvl
+ -- Top-level identifiers in this module,
+ -- (which have External Names)
+ -- are just like the imported case:
+ -- no need for the 'lifting' treatment
+ -- E.g. this is fine:
+ -- f x = x
+ -- g y = [| f 3 |]
+ = when (isExternalName name) (keepAlive name)
+ -- See Note [Keeping things alive for Template Haskell]
+
+ | otherwise
+ = -- Nested identifiers, such as 'x' in
+ -- E.g. \x -> [| h x |]
+ -- We must behave as if the reference to x was
+ -- h $(lift x)
+ -- We use 'x' itself as the splice proxy, used by
+ -- the desugarer to stitch it all back together.
+ -- If 'x' occurs many times we may get many identical
+ -- bindings of the same splice proxy, but that doesn't
+ -- matter, although it's a mite untidy.
+ do { traceRn (text "checkCrossStageLifting" <+> ppr name)
+ ; -- Update the pending splices
+ ; ps <- readMutVar ps_var
+ ; writeMutVar ps_var (PendingRnCrossStageSplice name : ps) }
+
+checkCrossStageLifting _ _ _ = return ()
+#endif /* GHCI */
+
+{-
+Note [Keeping things alive for Template Haskell]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider
+ f x = x+1
+ g y = [| f 3 |]
+
+Here 'f' is referred to from inside the bracket, which turns into data
+and mentions only f's *name*, not 'f' itself. So we need some other
+way to keep 'f' alive, lest it get dropped as dead code. That's what
+keepAlive does. It puts it in the keep-alive set, which subsequently
+ensures that 'f' stays as a top level binding.
+
+This must be done by the renamer, not the type checker (as of old),
+because the type checker doesn't typecheck the body of untyped
+brackets (Trac #8540).
+
+A thing can have a bind_lvl of outerLevel, but have an internal name:
+ foo = [d| op = 3
+ bop = op + 1 |]
+Here the bind_lvl of 'op' is (bogusly) outerLevel, even though it is
+bound inside a bracket. That is because we don't even even record
+binding levels for top-level things; the binding levels are in the
+LocalRdrEnv.
+
+So the occurrence of 'op' in the rhs of 'bop' looks a bit like a
+cross-stage thing, but it isn't really. And in fact we never need
+to do anything here for top-level bound things, so all is fine, if
+a bit hacky.
+
+For these chaps (which have Internal Names) we don't want to put
+them in the keep-alive set.
+
+Note [Quoting names]
+~~~~~~~~~~~~~~~~~~~~
+A quoted name 'n is a bit like a quoted expression [| n |], except that we
+have no cross-stage lifting (c.f. TcExpr.thBrackId). So, after incrementing
+the use-level to account for the brackets, the cases are:
+
+ bind > use Error
+ bind = use+1 OK
+ bind < use
+ Imported things OK
+ Top-level things OK
+ Non-top-level Error
+
+where 'use' is the binding level of the 'n quote. (So inside the implied
+bracket the level would be use+1.)
+
+Examples:
+
+ f 'map -- OK; also for top-level defns of this module
+
+ \x. f 'x -- Not ok (bind = 1, use = 1)
+ -- (whereas \x. f [| x |] might have been ok, by
+ -- cross-stage lifting
+
+ \y. [| \x. $(f 'y) |] -- Not ok (bind =1, use = 1)
+
+ [| \x. $(f 'x) |] -- OK (bind = 2, use = 1)
+-}