Opened 6 months ago

Last modified 2 months ago

#15562 new bug

`-XStrict -XNoStrict` is not neutral

Reported by: hvr Owned by:
Priority: normal Milestone: 8.6.1
Component: Compiler Version: 8.4.3
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description (last modified by hvr)

I assumed we already had a ticket about this, but it appears we have not.

I'm not saying this is a necessarily a bug in the implementation; but we should make sure this is properly documented in the user's guide, and ideally justify why it's done this way rather than the alternatives:

As described in StrictPragma,

Strict implies StrictData

Currently however the inverse case does not hold, i.e. NoStrict does *not* imply NoStrictData

This has the surprising property (assuming these were left-most flags on the CLI) that

  • -XStrict -XNoStrict == -XStrictData
  • -XStrictData -XNoStrict == -XStrictData

However, if -XNoStrict was to naively imply -XNoStrictData, we'd have the properties

  • -XStrict -XNoStrict == ∅
  • -XStrictData -XNoStrict == ∅

This might be a bit less confusing; another variant would be

  • -XStrict -XNoStrict == ∅
  • -XStrictData -XNoStrict == -XStrictData

(strictly speaking, it's not ∅ unless it's these are the left-most flags; also, any -XNo still has a cancellation effect on any flags occuring to the left on the CLI)

Btw, I'm not sure what the following means:

  • -XStrict -XNoStrictData == ?

Change History (6)

comment:1 Changed 6 months ago by hvr

Description: modified (diff)

comment:2 Changed 6 months ago by RyanGlScott

I think this extends far beyond Strict—in fact, I'd wager that it affects every language extension that implies other language extensions. As another data point, TypeFamilies implies ExplicitNamespaces, KindSignatures, and MonoLocalBinds. Here's a GHCi session which shows that -XTypeFamilies -XNoTypeFamilies is similarly un-neutral:

$ /opt/ghc/8.4.3/bin/ghci
GHCi, version 8.4.3: http://www.haskell.org/ghc/  :? for help                                                                                                                                             
Loaded GHCi configuration from /home/ryanglscott/.ghci
                                                                                                                                                    
λ> :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:

λ> :set -XTypeFamilies 
λ> :set
options currently set: none.
base language is: Haskell2010
with the following modifiers:
  -XNoDatatypeContexts
  -XExplicitNamespaces
  -XKindSignatures
  -XMonoLocalBinds
  -XNondecreasingIndentation
  -XTypeFamilies
GHCi-specific dynamic flag settings:
other dynamic, non-language, flag settings:
  -fignore-optim-changes
  -fignore-hpc-changes
  -fimplicit-import-qualified
warning settings:

λ> :set -XNoTypeFamilies 
λ> :set
options currently set: none.
base language is: Haskell2010
with the following modifiers:
  -XNoDatatypeContexts
  -XExplicitNamespaces
  -XKindSignatures
  -XMonoLocalBinds
  -XNondecreasingIndentation
GHCi-specific dynamic flag settings:
other dynamic, non-language, flag settings:
  -fignore-optim-changes
  -fignore-hpc-changes
  -fimplicit-import-qualified
warning settings:

So ultimately, the question here is: if enabling language extension A implies B, should NoA imply NoB? I'm not sure that it should. After all, someone legitimately might want to combine NoTypeFamilies with KindSignatures, but if NoTypeFamilies implied NoKindSignatures, then this order:

{-# LANGUAGE NoTypeFamilies #-}
{-# LANGUAGE KindSignatures #-}

Would enable KindSignatures, but this order:

{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE NoTypeFamilies #-}

Would disable KindSignatures! (This is especially noteworthy since many folks like to list language extensions in alphabetical order, so they're more likely to hit this scenario.)

Therefore, my inclination is to say that this is not a bug. Of course, if this behavior isn't documented, then it should be.

Do others have differing viewpoints?

comment:3 Changed 6 months ago by hvr

Well, with the current semantics, automatically reordering your LANGUAGE pragmas can change the effective set of enabled extensions. So that's something IDEs and refactoring tools will hopefully be aware of.

At least for now we have a simple heuristic such tooling can use to avoid changing the meaning of pragmas: groups of negative and positive pragmas do not commute. I.e. you are only allowed to reorder pragmas within a sequence of either positive or negative pragmas.

comment:4 Changed 6 months ago by goldfire

comment:3 requires that enabling one extension never disables another. However, this is not true! RebindableSyntax implies NoImplicitPrelude. Accordingly, ImplicitPrelude and RebindableSyntax do not commute. And, earlier this summer, TypeOperators implied NoStarIsType. This feature was removed because it made for a bad migration story, not because it violated this principle.

My vote would be simply not to make any guarantees of this sort. It's not hard for a tool to consult DynFlags.impliedXFlags and figure out what reorderings are OK.

comment:5 in reply to:  4 ; Changed 6 months ago by hvr

Replying to goldfire:

My vote would be simply not to make any guarantees of this sort. It's not hard for a tool to consult DynFlags.impliedXFlags and figure out what reorderings are OK.

While I agree now with that it's hopeless to give any guarantees; I disagree that consulting DynFlags.impliedXFlags is "not hard" for tools -- tools most often avoid to link against lib:ghc so they wouldn't have access to it; instead they tend to query e.g. ghc --supported-languages which unfortunately does not expose the relationships between those flags.

It would be very useful for tooling if ghc's CLI had some flag to dump an extended version of --supported-languages that's easy to parse

comment:6 in reply to:  5 Changed 2 months ago by chessai

It would be very useful for tooling if ghc's CLI had some flag to dump an extended version of --supported-languages that's easy to parse

What kind of format do you have in mind, if any?

Note: See TracTickets for help on using tickets.