[GHC] #15272: Handle implied flags more intuitively

#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

#15272: Handle implied flags more intuitively -------------------------------------+------------------------------------- Reporter: tdammers | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: 8.6.1 Component: Compiler | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: Other | Test Case: Blocked By: | Blocking: Related Tickets: #14963 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by nomeata): Hmm, would that still lead to the desired outcome if the user specifies `-fdefer-type-errors -fno-defer-type-holes`? Currently, I expect that after this, `defer-type-holes` is disabled. Under your scheme, it seems that `-fno-defered-type-holes` does not actually affect the list of ''explicit flags'' (because there is no `Opt_DeferTypeHoles` to undo), but then when we calculate the set of ''explicit flags'' `Opt_DeferTypeErrors` will imply `Opt_DeferTypeHoles`, and that flag will be enabled – against the user’s intention, I presume? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15272#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15272: Handle implied flags more intuitively -------------------------------------+------------------------------------- Reporter: tdammers | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: 8.8.1 Component: Compiler | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: Other | Test Case: Blocked By: | Blocking: Related Tickets: #14963 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * milestone: 8.6.1 => 8.8.1 Comment: This won't happen for 8.6. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15272#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15272: Handle implied flags more intuitively -------------------------------------+------------------------------------- Reporter: tdammers | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: 8.8.1 Component: Compiler | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: Other | Test Case: Blocked By: | Blocking: Related Tickets: #14963 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by tdammers): Replying to [comment:1 nomeata]:
Hmm, would that still lead to the desired outcome if the user specifies `-fdefer-type-errors -fno-defer-type-holes`?
Currently, I expect that after this, `defer-type-holes` is disabled.
Under your scheme, it seems that `-fno-defered-type-holes` does not actually affect the list of ''explicit flags'' (because there is no `Opt_DeferTypeHoles` to undo), but then when we calculate the set of ''explicit flags'' `Opt_DeferTypeErrors` will imply `Opt_DeferTypeHoles`, and that flag will be enabled – against the user’s intention, I presume?
Ah, you're right, that would still be a problem. Essentially though, asking for `-fdefer-type-errors -fno-defer-type-holes` is kind of an impossible request. Hmm. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15272#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15272: Handle implied flags more intuitively -------------------------------------+------------------------------------- Reporter: tdammers | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: 8.8.1 Component: Compiler | Version: 8.4.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: Other | Test Case: Blocked By: | Blocking: Related Tickets: #14963 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by tdammers): OK, simpler plan, as discussed in today's meeting: Just make disabling a flag also disable the implied flags. This can still lead to mildly surprising behavior, but it is consistent, easy to implement, and easy to document. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15272#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC