It looks like this only happens when -w is combined with -Wunrecognised-warning-flags. GHC seems to do the right thing when using -w and some other warning flag (make sure to use -fforce-recomp during testing).
For a newcomer. The code to change is in compiler/main/DynFlags.hs.
Error appears to be in parsing of flags before DynFlags.
See comment at end of ghc/compiler/main/CmdLineParser.hs
errorsToGhcException errs = UsageError $ intercalate "\n" $ [ l ++ ": " ++ e | (l, e) <- errs ]{- Note [Handling errors when parsing commandline flags]Parsing of static and mode flags happens before any session is started, i.e.,before the first call to 'GHC.withGhc'. Therefore, to report errors forinvalid usage of these two types of flags, we can not call any function thatneeds DynFlags, as there are no DynFlags available yet (unsafeGlobalDynFlagsis not set either). So we always print "on the commandline" as the location,which is true except for Api users, which is probably ok.When reporting errors for invalid usage of dynamic flags we /can/ make use ofDynFlags, and we do so explicitly in DynFlags.parseDynamicFlagsFull.Before, we called unsafeGlobalDynFlags when an invalid (combination of)flag(s) was given on the commandline, resulting in panics (#9963).-}
The actual error displayed seems to originate from ghc/compiler/main/StaticFlags.hs which calls the above 'errorsToGhcException' in CmdLineParser.hs
It looks like this only happens when -w is combined with -Wunrecognised-warning-flags.
To be clear, what I meant by that is that -w is too aggressive only when placed before -Wunrecognised-warning-flags. When -w is combined with other (existing) -W flags, GHC does the right thing (take the order in which the flags are passed into account).
Here is an example, with Test.hs containing:
module Test whereimport System.FilePath
TEST -w BEFORE.
-w disables all warning flags, but since we supply -Wunused-imports afterwards, we *do* get a warning:
$ ghc -w -Wunused-imports -fforce-recomp Test.hs[1 of 1] Compiling Test ( Test.hs, Test.o )Test.hs:2:1: warning: [-Wunused-imports] The import of ‘System.FilePath’ is redundant except perhaps to import instances from ‘System.FilePath’ To import instances alone, use: import System.FilePath()
TEST -w AFTER
We give -Wunused-imports first. But since we give -w afterwards, which reverts the previous flag, we do *not* get a warning:
warn about -Wfoo1 (since -Wunrecognised-warning-flags is on by default)
not warn about -Wfoo2 (since it comes after -w)
warn about -Wfoo3 (since it comes after -Wunrecognised-warning-flags)
Option 2
warn about all -Wfoo*, since -Wunrecognised-warning-flags came after -w, so -Wunrecognised-warning-flags is enabled
wozgonon: thanks for working on this! I think all these flags are Dynamic though, so I'm not sure that Note is relevant. The text "on the commandline" is coming from ghc/Main.hs most likely.
Right enough, I understand a little better now, though the error originates from DynFlags.hs:3022. See JB111 inserted into the code and in the output below.
Just a thought: would changing '-Wunrecognised-warning-flags' to '-unrecognised-warning-flags' do anything to solve the problem?
-- | This is where we handle unrecognised warning flags. We only issue a warning-- if -Wunrecognised-warning-flags is set. See Trac #11429 for context.unrecognisedWarning :: String -> Flag (CmdLineP DynFlags)unrecognisedWarning prefix = defFlag prefix (Prefix action) where action :: String -> EwM (CmdLineP DynFlags) () action flag = do f <- wopt Opt_WarnUnrecognisedWarningFlags <$> liftEwM getCmdLineState when f $ addWarn $ "JB111 unrecognised warning flag: -" ++ prefix ++ flag
Does not print warnings, as was noted in the ticket originally. Now if I add -Wdeprecated-flags, I now see all unrecognised warnings:
$ ghc Main.hs -Wfoo -w -Wunrecognised-warning-flags -Wdeprecated-flags -Wbar on the commandline: warning: unrecognised warning flag: -Wfoo on the commandline: warning: unrecognised warning flag: -Wbar
This is most likely due to the logic to show flag warnings
handleFlagWarnings :: DynFlags -> [Located String] -> IO ()handleFlagWarnings dflags warns = when (wopt Opt_WarnDeprecatedFlags dflags) $ do -- It would be nicer if warns :: [Located MsgDoc], but that -- has circular import problems. let bag = listToBag [ mkPlainWarnMsg dflags loc (text warn) | L loc warn <- warns ] printOrThrowWarnings dflags bag
So it would seem that Option 2 above is already implemented, albeit with some restrictions.
The most straightforward way to fix this would be to add Opt_UnrecognisedWarningFlags to handleFlagWarnings
I added a Phab differential. The changeset does indeed solve the original symptom, but it is probably not polished enough to be accepted. Nevertheless, I would really like to get some feedback, as I had to make changes in several places.