Commit 75321ffa authored by Eugene Akentyev's avatar Eugene Akentyev Committed by Ben Gamari

Add -fdefer-out-of-scope-variables flag (#12170).

Reviewers: simonpj, thomie, austin, bgamari

Reviewed By: simonpj, thomie, bgamari

Subscribers: simonpj, thomie

Differential Revision: https://phabricator.haskell.org/D2458

GHC Trac Issues: #12170
parent ca6d0eb0
......@@ -480,6 +480,7 @@ data GeneralFlag
| Opt_HelpfulErrors
| Opt_DeferTypeErrors
| Opt_DeferTypedHoles
| Opt_DeferOutOfScopeVariables
| Opt_PIC
| Opt_SccProfilingOn
| Opt_Ticky
......@@ -608,6 +609,7 @@ data WarningFlag =
| Opt_WarnUntickedPromotedConstructors
| Opt_WarnDerivingTypeable
| Opt_WarnDeferredTypeErrors
| Opt_WarnDeferredOutOfScopeVariables
| Opt_WarnNonCanonicalMonadInstances -- since 8.0
| Opt_WarnNonCanonicalMonadFailInstances -- since 8.0
| Opt_WarnNonCanonicalMonoidInstances -- since 8.0
......@@ -3248,6 +3250,8 @@ wWarningFlagsDeps = [
depFlagSpec "auto-orphans" Opt_WarnAutoOrphans
"it has no effect",
flagSpec "deferred-type-errors" Opt_WarnDeferredTypeErrors,
flagSpec "deferred-out-of-scope-variables"
Opt_WarnDeferredOutOfScopeVariables,
flagSpec "deprecations" Opt_WarnWarningsDeprecations,
flagSpec "deprecated-flags" Opt_WarnDeprecatedFlags,
flagSpec "deriving-typeable" Opt_WarnDerivingTypeable,
......@@ -3363,6 +3367,7 @@ fFlagsDeps = [
flagSpec "cpr-anal" Opt_CprAnal,
flagSpec "defer-type-errors" Opt_DeferTypeErrors,
flagSpec "defer-typed-holes" Opt_DeferTypedHoles,
flagSpec "defer-out-of-scope-variables" Opt_DeferOutOfScopeVariables,
flagSpec "dicts-cheap" Opt_DictsCheap,
flagSpec "dicts-strict" Opt_DictsStrict,
flagSpec "dmd-tx-dict-sel" Opt_DmdTxDictSel,
......@@ -3709,6 +3714,7 @@ default_PIC platform =
-- on
impliedGFlags :: [(GeneralFlag, TurnOnFlag, GeneralFlag)]
impliedGFlags = [(Opt_DeferTypeErrors, turnOn, Opt_DeferTypedHoles)
,(Opt_DeferTypeErrors, turnOn, Opt_DeferOutOfScopeVariables)
,(Opt_Strictness, turnOn, Opt_WorkerWrapper)
]
......@@ -3906,6 +3912,7 @@ standardWarnings -- see Note [Documenting warning flags]
Opt_WarnDeprecatedFlags,
Opt_WarnDeferredTypeErrors,
Opt_WarnTypedHoles,
Opt_WarnDeferredOutOfScopeVariables,
Opt_WarnPartialTypeSignatures,
Opt_WarnUnrecognisedPragmas,
Opt_WarnDuplicateExports,
......
......@@ -136,7 +136,14 @@ reportUnsolved wanted
| warn_partial_sigs = HoleWarn
| otherwise = HoleDefer
; report_unsolved (Just binds_var) False type_errors expr_holes type_holes wanted
; defer_out_of_scope <- goptM Opt_DeferOutOfScopeVariables
; warn_out_of_scope <- woptM Opt_WarnDeferredOutOfScopeVariables
; let out_of_scope_holes | not defer_out_of_scope = HoleError
| warn_out_of_scope = HoleWarn
| otherwise = HoleDefer
; report_unsolved (Just binds_var) False type_errors expr_holes
type_holes out_of_scope_holes wanted
; getTcEvBinds binds_var }
-- | Report *all* unsolved goals as errors, even if -fdefer-type-errors is on
......@@ -148,14 +155,14 @@ reportUnsolved wanted
-- and for simplifyDefault.
reportAllUnsolved :: WantedConstraints -> TcM ()
reportAllUnsolved wanted
= report_unsolved Nothing False TypeError HoleError HoleError wanted
= report_unsolved Nothing False TypeError HoleError HoleError HoleError wanted
-- | Report all unsolved goals as warnings (but without deferring any errors to
-- run-time). See Note [Safe Haskell Overlapping Instances Implementation] in
-- TcSimplify
warnAllUnsolved :: WantedConstraints -> TcM ()
warnAllUnsolved wanted
= report_unsolved Nothing True TypeWarn HoleWarn HoleWarn wanted
= report_unsolved Nothing True TypeWarn HoleWarn HoleWarn HoleWarn wanted
-- | Report unsolved goals as errors or warnings.
report_unsolved :: Maybe EvBindsVar -- cec_binds
......@@ -163,8 +170,10 @@ report_unsolved :: Maybe EvBindsVar -- cec_binds
-> TypeErrorChoice -- Deferred type errors
-> HoleChoice -- Expression holes
-> HoleChoice -- Type holes
-> HoleChoice -- Out of scope holes
-> WantedConstraints -> TcM ()
report_unsolved mb_binds_var err_as_warn type_errors expr_holes type_holes wanted
report_unsolved mb_binds_var err_as_warn type_errors expr_holes
type_holes out_of_scope_holes wanted
| isEmptyWC wanted
= return ()
| otherwise
......@@ -188,6 +197,7 @@ report_unsolved mb_binds_var err_as_warn type_errors expr_holes type_holes wante
, cec_errors_as_warns = err_as_warn
, cec_expr_holes = expr_holes
, cec_type_holes = type_holes
, cec_out_of_scope_holes = out_of_scope_holes
, cec_suppress = False -- See Note [Suppressing error messages]
, cec_warn_redundant = warn_redundant
, cec_binds = mb_binds_var }
......@@ -278,8 +288,13 @@ data ReportErrCtxt
, cec_defer_type_errors :: TypeErrorChoice -- Defer type errors until runtime
-- Irrelevant if cec_binds = Nothing
, cec_expr_holes :: HoleChoice -- Holes in expressions
, cec_type_holes :: HoleChoice -- Holes in types
-- cec_expr_holes is a union of:
-- cec_type_holes - a set of typed holes: '_', '_a', '_foo'
-- cec_out_of_scope_holes - a set of variables which are
-- out of scope: 'x', 'y', 'bar'
, cec_expr_holes :: HoleChoice -- Holes in expressions
, cec_type_holes :: HoleChoice -- Holes in types
, cec_out_of_scope_holes :: HoleChoice -- Out of scope holes
, cec_warn_redundant :: Bool -- True <=> -Wredundant-constraints
......@@ -621,10 +636,17 @@ maybeReportHoleError ctxt ct err
HoleWarn -> reportWarning (Reason Opt_WarnPartialTypeSignatures) err
HoleDefer -> return ()
-- Always report an error for out-of-scope variables
-- Unless -fdefer-out-of-scope-variables is on,
-- in which case the messages are discarded.
-- See Trac #12170, #12406
| isOutOfScopeCt ct
= -- Always report an error for out-of-scope variables
-- See Trac #12170, #12406
reportError err
= -- If deferring, report a warning only if -Wout-of-scope-variables is on
case cec_out_of_scope_holes ctxt of
HoleError -> reportError err
HoleWarn ->
reportWarning (Reason Opt_WarnDeferredOutOfScopeVariables) err
HoleDefer -> return ()
-- Otherwise this is a typed hole in an expression,
-- but not for an out-of-scope variable
......
......@@ -38,6 +38,9 @@ Compiler
syntax can be used, in addition to a new form for specifying the cost centre
name. See :ref:`scc-pragma` for examples.
- Added :ghc-flag:`-fdefer-out-of-scope-variables`, which converts variable
out of scope variables errors into warnings.
GHCi
~~~~
......
......@@ -9430,13 +9430,21 @@ Here are some more details:
containing holes, by using the :ghc-flag:`-fdefer-typed-holes` flag. This
flag defers errors produced by typed holes until runtime, and
converts them into compile-time warnings. These warnings can in turn
be suppressed entirely by :ghc-flag:`-fno-warn-typed-holes`).
be suppressed entirely by :ghc-flag:`-fno-warn-typed-holes`.
The result is that a hole will behave like ``undefined``, but with
The same behaviour for "``Variable out of scope``" errors, it terminates
compilation by default. You can defer such errors by using the
:ghc-flag:`-fdefer-out-of-scope-variables` flag. This flag defers errors
produced by out of scope variables until runtime, and
converts them into compile-time warnings. These warnings can in turn
be suppressed entirely by :ghc-flag:`-fno-warn-deferred-out-of-scope-variables`.
The result is that a hole or a variable will behave like ``undefined``, but with
the added benefits that it shows a warning at compile time, and will
show the same message if it gets evaluated at runtime. This behaviour
follows that of the :ghc-flag:`-fdefer-type-errors` option, which implies
:ghc-flag:`-fdefer-typed-holes`. See :ref:`defer-type-errors`.
:ghc-flag:`-fdefer-typed-holes` and :ghc-flag:`-fdefer-out-of-scope-variables`.
See :ref:`defer-type-errors`.
- All unbound identifiers are treated as typed holes, *whether or not
they start with an underscore*. The only difference is in the error
......@@ -9930,12 +9938,13 @@ will not prevent compilation. You can use
:ghc-flag:`-Wno-deferred-type-errors <-Wdeferred-type-errors>` to suppress these
warnings.
This flag implies the :ghc-flag:`-fdefer-typed-holes` flag, which enables this
behaviour for `typed holes <#typed-holes>`__. Should you so wish, it is
This flag implies the :ghc-flag:`-fdefer-typed-holes` and
:ghc-flag:`-fdefer-out-of-scope-variables` flags, which enables this
behaviour for `typed holes <#typed-holes>`__ and variables. Should you so wish, it is
possible to enable :ghc-flag:`-fdefer-type-errors` without enabling
:ghc-flag:`-fdefer-typed-holes`, by explicitly specifying
:ghc-flag:`-fno-defer-typed-holes` on the command-line after the
:ghc-flag:`-fdefer-type-errors` flag.
:ghc-flag:`-fdefer-typed-holes` or :ghc-flag:`-fdefer-out-of-scope-variables`,
by explicitly specifying :ghc-flag:`-fno-defer-typed-holes` or :ghc-flag:`-fno-defer-out-of-scope-variables`
on the command-line after the :ghc-flag:`-fdefer-type-errors` flag.
At runtime, whenever a term containing a type error would need to be
evaluated, the error is converted into a runtime exception of type
......
......@@ -152,7 +152,8 @@ of ``-W(no-)*``.
.. ghc-flag:: -fdefer-typed-holes
Defer typed holes errors until runtime. This will turn the errors
Defer typed holes errors (errors about names with a leading underscore
(e.g., “_”, “_foo”, “_bar”)) until runtime. This will turn the errors
produced by :ref:`typed holes <typed-holes>` into warnings. Using a value
that depends on a typed hole produces a runtime error, the same as
:ghc-flag:`-fdefer-type-errors` (which implies this option). See :ref:`typed-holes`
......@@ -160,6 +161,16 @@ of ``-W(no-)*``.
Implied by :ghc-flag:`-fdefer-type-errors`. See also :ghc-flag:`-Wtyped-holes`.
.. ghc-flag:: -fdefer-out-of-scope-variables
Defer variable out of scope errors (errors about names without a leading underscore)
until runtime. This will turn variable-out-of-scope errors into warnings.
Using a value that depends on a typed hole produces a runtime error,
the same as :ghc-flag:`-fdefer-type-errors` (which implies this option).
See :ref:`typed-holes` and :ref:`defer-type-errors`.
Implied by :ghc-flag:`-fdefer-type-errors`. See also :ghc-flag:`-Wdeferred-out-of-scope-variables`.
.. ghc-flag:: -Wpartial-type-signatures
Determines whether the compiler reports holes in partial type
......
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -fdefer-out-of-scope-variables #-}
main :: IO ()
main = smth
T12170b.hs:5:8: warning: [-Wdeferred-out-of-scope-variables (in -Wdefault)]
Variable not in scope: smth :: IO ()
......@@ -537,3 +537,4 @@ test('T12185', normal, compile, [''])
test('T12133', normal, compile, [''])
test('T12381', normal, compile, [''])
test('T12082', normal, compile, [''])
test('T12170b', normal, compile, [''])
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -fdefer-out-of-scope-variables #-}
module T12170a where
-- import Control.Monad -- comment this out to cause error
import Data.IORef
class MonadRef m where
type Ref m :: * -> *
newRef :: a -> m (Ref m a)
readRef :: Ref m a -> m a
instance MonadRef IO where
type Ref IO = IORef
newRef = newIORef
readRef = readIORef
foo :: IO ()
foo = newRef (pure ()) >>= join . readRef
T12170a.hs:20:7: error:
• Couldn't match type ‘Ref m0’ with ‘IORef’
Expected type: IO (Ref m0 (f0 ()))
Actual type: IO (Ref IO (f0 ()))
The type variable ‘m0’ is ambiguous
• In the first argument of ‘(>>=)’, namely ‘newRef (pure ())’
In the expression: newRef (pure ()) >>= join . readRef
In an equation for ‘foo’: foo = newRef (pure ()) >>= join . readRef
\ No newline at end of file
......@@ -429,3 +429,4 @@ test('T12151', normal, compile_fail, [''])
test('T7437', normal, compile_fail, [''])
test('T12177', normal, compile_fail, [''])
test('T12406', normal, compile_fail, [''])
test('T12170a', normal, compile_fail, [''])
......@@ -51,7 +51,9 @@ warningsOptions =
, flag { flagName = "-fdefer-type-errors"
, flagDescription =
"Turn type errors into warnings, :ref:`deferring the error until "++
"runtime <defer-type-errors>`. Implies :ghc-flag:`-fdefer-typed-holes`. "++
"runtime <defer-type-errors>`. Implies "++
":ghc-flag:`-fdefer-typed-holes` and "++
":ghc-flag:`-fdefer-out-of-scope-variables`. "++
"See also :ghc-flag:`-Wdeferred-type-errors`"
, flagType = DynamicFlag
, flagReverse = "-fno-defer-type-errors"
......@@ -65,6 +67,14 @@ warningsOptions =
, flagType = DynamicFlag
, flagReverse = "-fno-defer-typed-holes"
}
, flag { flagName = "-fdefer-out-of-scope-variables"
, flagDescription =
"Convert variable out of scope variables errors into warnings. "++
"Implied by :ghc-flag:`-fdefer-type-errors`. "++
"See also :ghc-flag:`-Wdeferred-out-of-scope-variables`."
, flagType = DynamicFlag
, flagReverse = "-fno-defer-out-of-scope-variables"
}
, flag { flagName = "-fhelpful-errors"
, flagDescription = "Make suggestions for mis-spelled names."
, flagType = DynamicFlag
......@@ -398,6 +408,14 @@ warningsOptions =
, flagType = DynamicFlag
, flagReverse = "-Wno-typed-holes"
}
, flag { flagName = "-Wdeferred-out-of-scope-variables"
, flagDescription =
"Report warnings when variable out-of-scope errors are "++
":ref:`deferred until runtime <defer-out-of-scope-variables>`. "++
"See :ghc-flag:`-fdefer-out-of-scope-variables`."
, flagType = DynamicFlag
, flagReverse = "-Wno-deferred-out-of-scope-variables"
}
, flag { flagName = "-Wpartial-type-signatures"
, flagDescription =
"warn about holes in partial type signatures when "++
......
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