[GHC] #15272: Handle implied flags more intuitively
GHC
ghc-devs at haskell.org
Thu Jun 14 14:31:09 UTC 2018
#15272: Handle implied flags more intuitively
-------------------------------------+-------------------------------------
Reporter: tdammers | Owner: (none)
Type: feature | Status: new
request |
Priority: normal | Milestone: 8.6.1
Component: Compiler | Version: 8.4.3
Keywords: | Operating System: Unknown/Multiple
Architecture: | Type of failure: Other
Unknown/Multiple |
Test Case: | Blocked By:
Blocking: | Related Tickets: #14963
Differential Rev(s): | Wiki Page:
-------------------------------------+-------------------------------------
Many flags in GHC imply other flags. For example, enabling `-fdefer-type-
errors` also enables `-fdefer-type-holes` and `-fdefer-out-of-scope-
variables`:
{{{
GHCi, version 8.4.2: http://www.haskell.org/ghc/ :? for help
Prelude> :set
options currently set: none.
base language is: Haskell2010
with the following modifiers:
-XNoDatatypeContexts
-XNondecreasingIndentation
GHCi-specific dynamic flag settings:
other dynamic, non-language, flag settings:
-fignore-optim-changes
-fignore-hpc-changes
-fimplicit-import-qualified
warning settings:
Prelude> :set -fdefer-type
-fdefer-type-errors -fdefer-typed-holes
Prelude> :set -fdefer-type-errors
Prelude> :set
options currently set: none.
base language is: Haskell2010
with the following modifiers:
-XNoDatatypeContexts
-XNondecreasingIndentation
GHCi-specific dynamic flag settings:
other dynamic, non-language, flag settings:
-fdefer-type-errors
-fdefer-typed-holes
-fdefer-out-of-scope-variables
-fignore-optim-changes
-fignore-hpc-changes
-fimplicit-import-qualified
warning settings:
}}}
This is fine.
Disabling previously enabled flags does not disable the implied flags:
`-fno-defer-type-errors` does not also set `-fno-defer-type-holes` and
`-fno-defer-out-of-scope-variables`. This is also fine in principle;
otherwise, setting `-fdefer-type-holes -fno-defer-type-errors` would do
the unintuitive thing of setting neither flag.
But it does lead to unintuitive behavior when the implied flags have never
been touched explicitly: setting `-fdefer-type-errors`, and then later
`-fno-defer-type-errors`, leaves `-fdefer-type-holes` and `-fdefer-out-of-
scope-variables` set, even though the user never asked for them:
{{{
Prelude> :set -fdefer-type-errors
Prelude> :set
options currently set: none.
base language is: Haskell2010
with the following modifiers:
-XNoDatatypeContexts
-XNondecreasingIndentation
GHCi-specific dynamic flag settings:
other dynamic, non-language, flag settings:
-fdefer-type-errors
-fdefer-typed-holes
-fdefer-out-of-scope-variables
-fignore-optim-changes
-fignore-hpc-changes
-fimplicit-import-qualified
warning settings:
Prelude> :set -fno-defer-type-errors
Prelude> :set
options currently set: none.
base language is: Haskell2010
with the following modifiers:
-XNoDatatypeContexts
-XNondecreasingIndentation
GHCi-specific dynamic flag settings:
other dynamic, non-language, flag settings:
-fdefer-typed-holes <- These two are
-fdefer-out-of-scope-variables <- unexpected!
-fignore-optim-changes
-fignore-hpc-changes
-fimplicit-import-qualified
warning settings:
}}}
So we have a conundrum: when unsetting a flag, we may or may not need to
unset the options it implies - neither is always correct, so in order to
figure out what to do, we need to know *why* the flag was set. But it's
even worse: if we have a flag X, and two other flags A and B, both of
which imply X, and we first set A and B, and then unset B, we would have
to keep X set, because otherwise we would break A. But if we then also
unset A, we would have to also unset X. Tracking which option implicitly
enabled which other option, and correctly resolving that, seems like
terribly messy business. So I propose a different solution:
1. Maintain one set of `DynFlags` that holds only those flags that were
requested explicitly. Setting `-fdefer-type-errors` would only set
`Opt_DeferTypeErrors` in this set, but none of the implied flags; and
`-fno-defer-type-errors` would simply unset `Opt_DeferTypeErrors`.
2. Maintain another set of `DynFlags` that holds the effective flags: we
can always calculate these based on the explicit flags. We could either do
this on the fly, just before running the actual compilation / evaluation,
or we could keep the data structure around and only update it when the
explicit flags have changed.
This way, setting and unsetting flags will always do the right thing, and
we don't throw away the information about which flags were set explicitly.
This is probably more relevant in GHCi, because in plain GHC, one would
typically just set all the needed flags at once and then never change them
again until the next run; but in GHCi, modifying compiler flags between
evaluations is a common thing to do.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/15272>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list