Commit 41afbb3f authored by Matthew Pickering's avatar Matthew Pickering Committed by Ben Gamari

Add flag -fno-it

This flag stops ghci creating the special variable `it`
after evaluating an expression. This stops ghci leaking
as much memory when evaluating expressions. See #14336

Reviewers: bgamari

Reviewed By: bgamari

Subscribers: rwbarton, thomie, carter

GHC Trac Issues: #14336

Differential Revision: https://phabricator.haskell.org/D4299
parent 2feed118
......@@ -522,6 +522,7 @@ data GeneralFlag
| Opt_GhciSandbox
| Opt_GhciHistory
| Opt_LocalGhciHistory
| Opt_NoIt
| Opt_HelpfulErrors
| Opt_DeferTypeErrors
| Opt_DeferTypedHoles
......@@ -3824,6 +3825,7 @@ fFlagsDeps = [
flagSpec "gen-manifest" Opt_GenManifest,
flagSpec "ghci-history" Opt_GhciHistory,
flagGhciSpec "local-ghci-history" Opt_LocalGhciHistory,
flagGhciSpec "no-it" Opt_NoIt,
flagSpec "ghci-sandbox" Opt_GhciSandbox,
flagSpec "helpful-errors" Opt_HelpfulErrors,
flagSpec "hpc" Opt_Hpc,
......
......@@ -2010,17 +2010,23 @@ tcUserStmt (L loc (BodyStmt expr _ _ _))
(mkRnSyntaxExpr thenIOName)
noSyntaxExpr placeHolderType
-- The plans are:
-- A. [it <- e; print it] but not if it::()
-- B. [it <- e]
-- C. [let it = e; print it]
--
-- Ensure that type errors don't get deferred when type checking the
-- naked expression. Deferring type errors here is unhelpful because the
-- expression gets evaluated right away anyway. It also would potentially
-- emit two redundant type-error warnings, one from each plan.
; plan <- unsetGOptM Opt_DeferTypeErrors $
unsetGOptM Opt_DeferTypedHoles $ runPlans [
-- NewA
no_it_a = L loc $ BodyStmt (nlHsApps bindIOName
[rn_expr , nlHsVar interPrintName])
(mkRnSyntaxExpr thenIOName)
noSyntaxExpr placeHolderType
no_it_b = L loc $ BodyStmt (rn_expr)
(mkRnSyntaxExpr thenIOName)
noSyntaxExpr placeHolderType
no_it_c = L loc $ BodyStmt (nlHsApp (nlHsVar interPrintName) rn_expr)
(mkRnSyntaxExpr thenIOName)
noSyntaxExpr placeHolderType
-- See Note [GHCi Plans]
it_plans = [
-- Plan A
do { stuff@([it_id], _) <- tcGhciStmts [bind_stmt, print_it]
; it_ty <- zonkTcType (idType it_id)
......@@ -2039,6 +2045,25 @@ tcUserStmt (L loc (BodyStmt expr _ _ _))
--- checkNoErrs defeats the error recovery of let-bindings
; tcGhciStmts [let_stmt, print_it] } ]
-- Plans where we don't bind "it"
no_it_plans = [
tcGhciStmts [no_it_a] ,
tcGhciStmts [no_it_b] ,
tcGhciStmts [no_it_c] ]
-- Ensure that type errors don't get deferred when type checking the
-- naked expression. Deferring type errors here is unhelpful because the
-- expression gets evaluated right away anyway. It also would potentially
-- emit two redundant type-error warnings, one from each plan.
; generate_it <- goptM Opt_NoIt
; plan <- unsetGOptM Opt_DeferTypeErrors $
unsetGOptM Opt_DeferTypedHoles $
runPlans $ if generate_it
then no_it_plans
else it_plans
; fix_env <- getFixityEnv
; return (plan, fix_env) }
......@@ -2080,6 +2105,27 @@ tcUserStmt rdr_stmt@(L loc _)
(mkRnSyntaxExpr thenIOName) noSyntaxExpr
placeHolderType
{-
Note [GHCi Plans]
When a user types an expression in the repl we try to print it in three different
ways. Also, depending on whether -fno-it is set, we bind a variable called `it`
which can be used to refer to the result of the expression subsequently in the repl.
The normal plans are :
A. [it <- e; print e] but not if it::()
B. [it <- e]
C. [let it = e; print it]
When -fno-it is set, the plans are:
A. [e >>= print]
B. [e]
C. [let it = e in print it]
The reason for -fno-it is explained in #14336. `it` can lead to the repl
leaking memory as it is repeatedly queried.
-}
-- | Typecheck the statements given and then return the results of the
-- statement in the form 'IO [()]'.
tcGhciStmts :: [GhciLStmt GhcRn] -> TcM PlanResult
......
......@@ -1027,6 +1027,20 @@ The corresponding translation for an IO-typed ``e`` is
Note that ``it`` is shadowed by the new value each time you evaluate a
new expression, and the old value of ``it`` is lost.
In order to stop the value ``it`` being bound on each command, the flag
:ghc-flag:`-fno-it` can be set. The ``it`` variable can be the source
of space leaks due to how shadowed declarations are handled by
GHCi (see :ref:`ghci-decls`).
.. ghc-flag:: -fno-it
:shortdesc: No longer set the special variable ``it``.
:type: dynamic
:reverse: -fno-no-it
:category:
When this flag is set, the variable ``it`` will no longer be set
to the result of the previously evaluated expression.
.. _extended-default-rules:
Type defaulting in GHCi
......
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