From c846c51fedc309096f9e5b0c1f8a2b1392f81786 Mon Sep 17 00:00:00 2001 From: Ilia Baryshnikov Date: Fri, 15 May 2026 11:23:24 +0300 Subject: [PATCH] Allow case insensitive bools and move to numeric render Co-authored-by: Jappie Klooster --- Cabal-syntax/src/Distribution/Parsec.hs | 8 +- .../src/Distribution/Parsec/Warning.hs | 2 - Cabal-tests/tests/ParserTests.hs | 1 - .../tests/ParserTests/warnings/bool.cabal | 12 -- Cabal/src/Distribution/Simple/Command.hs | 10 -- Cabal/src/Distribution/Simple/Compiler.hs | 58 ++++++--- Cabal/src/Distribution/Simple/Setup/Config.hs | 28 ++--- Cabal/src/Distribution/Types/DumpBuildInfo.hs | 11 +- .../src/Distribution/Client/Config.hs | 88 ++++---------- .../Client/ProjectConfig/Legacy.hs | 112 ++++++------------ .../Client/ProjectOrchestration.hs | 12 +- changelog.d/11828.md | 12 ++ 12 files changed, 131 insertions(+), 223 deletions(-) delete mode 100644 Cabal-tests/tests/ParserTests/warnings/bool.cabal create mode 100644 changelog.d/11828.md diff --git a/Cabal-syntax/src/Distribution/Parsec.hs b/Cabal-syntax/src/Distribution/Parsec.hs index 9b43b6e41a2..6d384418370 100644 --- a/Cabal-syntax/src/Distribution/Parsec.hs +++ b/Cabal-syntax/src/Distribution/Parsec.hs @@ -252,15 +252,11 @@ instance Parsec Bool where parsec = P.munch1 isAlpha >>= postprocess where postprocess str - | str == "True" = pure True - | str == "False" = pure False - | lstr == "true" = parsecWarning PWTBoolCase caseWarning *> pure True - | lstr == "false" = parsecWarning PWTBoolCase caseWarning *> pure False + | lstr == "true" = pure True + | lstr == "false" = pure False | otherwise = fail $ "Not a boolean: " ++ str where lstr = map toLower str - caseWarning = - "Boolean values are case sensitive, use 'True' or 'False'." instance Parsec a => Parsec (Last a) where parsec = parsecLast diff --git a/Cabal-syntax/src/Distribution/Parsec/Warning.hs b/Cabal-syntax/src/Distribution/Parsec/Warning.hs index 65b1471b054..2472c544b8f 100644 --- a/Cabal-syntax/src/Distribution/Parsec/Warning.hs +++ b/Cabal-syntax/src/Distribution/Parsec/Warning.hs @@ -25,8 +25,6 @@ data PWarnType PWTOther | -- | Invalid UTF encoding PWTUTF - | -- | @true@ or @false@, not @True@ or @False@ - PWTBoolCase | -- | there are version with tags PWTVersionTag | -- | New syntax used, but no @cabal-version: >= 1.2@ specified diff --git a/Cabal-tests/tests/ParserTests.hs b/Cabal-tests/tests/ParserTests.hs index 42ab00ae9f2..88c40fde27f 100644 --- a/Cabal-tests/tests/ParserTests.hs +++ b/Cabal-tests/tests/ParserTests.hs @@ -68,7 +68,6 @@ warningTests = testGroup "warnings triggered" , warningTest PWTLexNBSP "nbsp.cabal" , warningTest PWTLexTab "tab.cabal" , warningTest PWTUTF "utf8.cabal" - , warningTest PWTBoolCase "bool.cabal" , warningTest PWTVersionTag "versiontag.cabal" , warningTest PWTNewSyntax "newsyntax.cabal" , warningTest PWTOldSyntax "oldsyntax.cabal" diff --git a/Cabal-tests/tests/ParserTests/warnings/bool.cabal b/Cabal-tests/tests/ParserTests/warnings/bool.cabal deleted file mode 100644 index 34e6e0f8f22..00000000000 --- a/Cabal-tests/tests/ParserTests/warnings/bool.cabal +++ /dev/null @@ -1,12 +0,0 @@ -name: bool -version: 1 -cabal-version: >= 1.8 - -flag foo - manual: true - -library - build-depends: base >= 4.9 && <4.10 - if flag(foo) - build-depends: containers - hs-source-dirs: . diff --git a/Cabal/src/Distribution/Simple/Command.hs b/Cabal/src/Distribution/Simple/Command.hs index 0fe65f8d751..6f0eced8ad0 100644 --- a/Cabal/src/Distribution/Simple/Command.hs +++ b/Cabal/src/Distribution/Simple/Command.hs @@ -79,7 +79,6 @@ module Distribution.Simple.Command , reqArg' , optArg , optArg' - , optArgDef' , noArg , boolOpt , boolOpt' @@ -280,15 +279,6 @@ optArg' optArg' ad mkflag showflag = optArg ad (succeedReadE (mkflag . Just)) ("", mkflag Nothing) showflag -optArgDef' - :: Monoid b - => ArgPlaceHolder - -> (String, Maybe String -> b) - -> (b -> [Maybe String]) - -> MkOptDescr (a -> b) (b -> a -> a) a -optArgDef' ad (dv, mkflag) showflag = - optArg ad (succeedReadE (mkflag . Just)) (dv, mkflag Nothing) showflag - noArg :: Eq b => b -> MkOptDescr (a -> b) (b -> a -> a) a noArg flag sf lf d = choiceOpt [(flag, (sf, lf), d)] sf lf d diff --git a/Cabal/src/Distribution/Simple/Compiler.hs b/Cabal/src/Distribution/Simple/Compiler.hs index 4f66f90eea8..72f1609c536 100644 --- a/Cabal/src/Distribution/Simple/Compiler.hs +++ b/Cabal/src/Distribution/Simple/Compiler.hs @@ -1,6 +1,8 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveTraversable #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE PatternSynonyms #-} ----------------------------------------------------------------------------- @@ -54,11 +56,13 @@ module Distribution.Simple.Compiler -- * Support for optimisation levels , OptimisationLevel (..) - , flagToOptimisationLevel + , toOptimisationLevel + , fromOptimisationLevel -- * Support for debug info levels , DebugInfoLevel (..) - , flagToDebugInfoLevel + , toDebugInfoLevel + , fromDebugInfoLevel -- * Support for language extensions , CompilerFlag @@ -112,6 +116,7 @@ import Language.Haskell.Extension import Data.Bool (bool) import qualified Data.Map as Map (lookup) +import Distribution.Simple.Flag (Flag, pattern Flag, pattern NoFlag) import System.Directory (canonicalizePath) data Compiler = Compiler @@ -329,12 +334,16 @@ parsecOptimisationLevel = boolParser <|> intParser boolParser = bool NoOptimisation NormalOptimisation <$> parsec intParser = intToOptimisationLevel <$> integral -flagToOptimisationLevel :: Maybe String -> OptimisationLevel -flagToOptimisationLevel Nothing = NormalOptimisation -flagToOptimisationLevel (Just s) = case reads s of +toOptimisationLevel :: String -> OptimisationLevel +toOptimisationLevel s = case reads s of [(i, "")] -> intToOptimisationLevel i _ -> error $ "Can't parse optimisation level " ++ s +fromOptimisationLevel :: Flag OptimisationLevel -> String +fromOptimisationLevel = \case + Flag op -> show $ fromEnum op + NoFlag -> "1" + intToOptimisationLevel :: Int -> OptimisationLevel intToOptimisationLevel i | i >= minLevel && i <= maxLevel = toEnum i @@ -374,22 +383,33 @@ instance Parsec DebugInfoLevel where parsec = parsecDebugInfoLevel parsecDebugInfoLevel :: CabalParsing m => m DebugInfoLevel -parsecDebugInfoLevel = flagToDebugInfoLevel . pure <$> parsecToken - -flagToDebugInfoLevel :: Maybe String -> DebugInfoLevel -flagToDebugInfoLevel Nothing = NormalDebugInfo -flagToDebugInfoLevel (Just s) = case reads s of - [(i, "")] - | i >= fromEnum (minBound :: DebugInfoLevel) - && i <= fromEnum (maxBound :: DebugInfoLevel) -> - toEnum i - | otherwise -> - error $ - "Bad debug info level: " - ++ show i - ++ ". Valid values are 0..3" +parsecDebugInfoLevel = boolParser <|> intParser + where + boolParser = bool NoDebugInfo NormalDebugInfo <$> parsec + intParser = intToDebugInfoLevel <$> integral + +toDebugInfoLevel :: String -> DebugInfoLevel +toDebugInfoLevel s = case reads s of + [(i, "")] -> intToDebugInfoLevel i _ -> error $ "Can't parse debug info level " ++ s +fromDebugInfoLevel :: Flag DebugInfoLevel -> String +fromDebugInfoLevel = \case + Flag db -> show $ fromEnum db + NoFlag -> "0" + +intToDebugInfoLevel :: Int -> DebugInfoLevel +intToDebugInfoLevel i + | i >= minLevel && i <= maxLevel = toEnum i + | otherwise = + error $ + "Bad debug info level: " + ++ show i + ++ ". Valid values are 0..3" + where + minLevel = fromEnum (minBound :: DebugInfoLevel) + maxLevel = fromEnum (maxBound :: DebugInfoLevel) + -- ------------------------------------------------------------ -- * Languages and Extensions diff --git a/Cabal/src/Distribution/Simple/Setup/Config.hs b/Cabal/src/Distribution/Simple/Setup/Config.hs index 0d1803c2a56..726e1122ee6 100644 --- a/Cabal/src/Distribution/Simple/Setup/Config.hs +++ b/Cabal/src/Distribution/Simple/Setup/Config.hs @@ -2,6 +2,7 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ViewPatterns #-} @@ -569,14 +570,12 @@ configureOptions showOrParseArgs = "optimization" configOptimization (\v flags -> flags{configOptimization = v}) - [ optArgDef' + [ reqArg' "n" - (show NoOptimisation, Flag . flagToOptimisationLevel) - ( \f -> case f of - Flag NoOptimisation -> [] - Flag NormalOptimisation -> [Nothing] - Flag MaximumOptimisation -> [Just "2"] - _ -> [] + (Flag . toOptimisationLevel) + ( \case + NoFlag -> [] + flag -> [fromOptimisationLevel flag] ) "O" ["enable-optimization", "enable-optimisation"] @@ -591,17 +590,14 @@ configureOptions showOrParseArgs = "debug-info" configDebugInfo (\v flags -> flags{configDebugInfo = v}) - [ optArg' + [ reqArg' "n" - (Flag . flagToDebugInfoLevel) - ( \f -> case f of - Flag NoDebugInfo -> [] - Flag MinimalDebugInfo -> [Just "1"] - Flag NormalDebugInfo -> [Nothing] - Flag MaximalDebugInfo -> [Just "3"] - _ -> [] + (Flag . toDebugInfoLevel) + ( \case + NoFlag -> [] + flag -> [fromDebugInfoLevel flag] ) - "" + "g" ["enable-debug-info"] "Emit debug info (n is 0--3, default is 0)" , noArg diff --git a/Cabal/src/Distribution/Types/DumpBuildInfo.hs b/Cabal/src/Distribution/Types/DumpBuildInfo.hs index b946093b487..21519948e0b 100644 --- a/Cabal/src/Distribution/Types/DumpBuildInfo.hs +++ b/Cabal/src/Distribution/Types/DumpBuildInfo.hs @@ -1,11 +1,13 @@ {-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE LambdaCase #-} module Distribution.Types.DumpBuildInfo ( DumpBuildInfo (..) + , fromDumpBuildInfo ) where -import Distribution.Compat.Prelude -import Distribution.Parsec +import Distribution.Compat.Prelude (Binary, Generic, NFData, Structured) +import Distribution.Parsec (CabalParsing, Parsec (..)) data DumpBuildInfo = NoDumpBuildInfo @@ -24,3 +26,8 @@ parsecDumpBuildInfo = boolToDumpBuildInfo <$> parsec boolToDumpBuildInfo :: Bool -> DumpBuildInfo boolToDumpBuildInfo bool = if bool then DumpBuildInfo else NoDumpBuildInfo + +fromDumpBuildInfo :: DumpBuildInfo -> String +fromDumpBuildInfo = \case + NoDumpBuildInfo -> "False" + DumpBuildInfo -> "True" diff --git a/cabal-install/src/Distribution/Client/Config.hs b/cabal-install/src/Distribution/Client/Config.hs index b42cfee9916..00bbf87e781 100644 --- a/cabal-install/src/Distribution/Client/Config.hs +++ b/cabal-install/src/Distribution/Client/Config.hs @@ -1,4 +1,5 @@ {-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE PatternSynonyms #-} ----------------------------------------------------------------------------- @@ -137,7 +138,6 @@ import Distribution.Compiler import Distribution.Deprecated.ParseUtils ( FieldDescr (..) , PError (..) - , PWarning (..) , ParseResult (..) , liftField , lineNo @@ -166,8 +166,8 @@ import Distribution.Simple.Command , commandDefaultFlags ) import Distribution.Simple.Compiler - ( DebugInfoLevel (..) - , OptimisationLevel (..) + ( fromDebugInfoLevel + , fromOptimisationLevel ) import Distribution.Simple.InstallDirs ( InstallDirs (..) @@ -1189,75 +1189,29 @@ configFieldDescriptions src = (Flag <$> parsec <|> pure NoFlag) configHcFlavor (\v flags -> flags{configHcFlavor = v}) - , -- TODO: The following is a temporary fix. The "optimization" - -- and "debug-info" fields are OptArg, and viewAsFieldDescr - -- fails on that. Instead of a hand-written hackaged parser - -- and printer, we should handle this case properly in the - -- library. - liftField - configOptimization - ( \v flags -> - flags{configOptimization = v} - ) - $ let name = "optimization" - in FieldDescr - name - ( \f -> case f of - Flag NoOptimisation -> Disp.text "False" - Flag NormalOptimisation -> Disp.text "True" - Flag MaximumOptimisation -> Disp.text "2" - _ -> Disp.empty - ) - ( \line str _ -> case () of - _ - | str == "False" -> ParseOk [] (Flag NoOptimisation) - | str == "True" -> ParseOk [] (Flag NormalOptimisation) - | str == "0" -> ParseOk [] (Flag NoOptimisation) - | str == "1" -> ParseOk [] (Flag NormalOptimisation) - | str == "2" -> ParseOk [] (Flag MaximumOptimisation) - | lstr == "false" -> ParseOk [caseWarning] (Flag NoOptimisation) - | lstr == "true" -> - ParseOk - [caseWarning] - (Flag NormalOptimisation) - | otherwise -> ParseFailed (NoParse name line) - where - lstr = lowercase str - caseWarning = - PWarning $ - "The '" - ++ name - ++ "' field is case sensitive, use 'True' or 'False'." - ) + , liftField configOptimization (\v flags -> flags{configOptimization = v}) $ + let name = "optimization" + in FieldDescr + name + ( \case + NoFlag -> Disp.empty + flag -> Disp.text $ fromOptimisationLevel flag + ) + ( \line str _ -> case maybe NoFlag Flag (simpleParsec str) of + NoFlag -> ParseFailed (NoParse name line) + flag -> ParseOk [] flag + ) , liftField configDebugInfo (\v flags -> flags{configDebugInfo = v}) $ let name = "debug-info" in FieldDescr name - ( \f -> case f of - Flag NoDebugInfo -> Disp.text "False" - Flag MinimalDebugInfo -> Disp.text "1" - Flag NormalDebugInfo -> Disp.text "True" - Flag MaximalDebugInfo -> Disp.text "3" - _ -> Disp.empty + ( \case + NoFlag -> Disp.empty + flag -> Disp.text $ fromDebugInfoLevel flag ) - ( \line str _ -> case () of - _ - | str == "False" -> ParseOk [] (Flag NoDebugInfo) - | str == "True" -> ParseOk [] (Flag NormalDebugInfo) - | str == "0" -> ParseOk [] (Flag NoDebugInfo) - | str == "1" -> ParseOk [] (Flag MinimalDebugInfo) - | str == "2" -> ParseOk [] (Flag NormalDebugInfo) - | str == "3" -> ParseOk [] (Flag MaximalDebugInfo) - | lstr == "false" -> ParseOk [caseWarning] (Flag NoDebugInfo) - | lstr == "true" -> ParseOk [caseWarning] (Flag NormalDebugInfo) - | otherwise -> ParseFailed (NoParse name line) - where - lstr = lowercase str - caseWarning = - PWarning $ - "The '" - ++ name - ++ "' field is case sensitive, use 'True' or 'False'." + ( \line str _ -> case maybe NoFlag Flag (simpleParsec str) of + NoFlag -> ParseFailed (NoParse name line) + flag -> ParseOk [] flag ) ] ++ toSavedConfig diff --git a/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs b/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs index fc4faa6a64a..0916b4446cd 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs @@ -86,9 +86,9 @@ import Distribution.PackageDescription.Configuration (simplifyWithSysParams) import Distribution.Simple.Compiler ( Compiler (..) , CompilerInfo (..) - , DebugInfoLevel (..) - , OptimisationLevel (..) , compilerInfo + , fromDebugInfoLevel + , fromOptimisationLevel , interpretPackageDB ) import Distribution.Simple.InstallDirs (CopyDest (NoCopyDest)) @@ -108,7 +108,6 @@ import Distribution.Simple.Setup ( BenchmarkFlags (..) , CommonSetupFlags (..) , ConfigFlags (..) - , DumpBuildInfo (DumpBuildInfo, NoDumpBuildInfo) , Flag , HaddockFlags (..) , TestFlags (..) @@ -131,7 +130,6 @@ import Distribution.Simple.Setup ) import Distribution.Simple.Utils ( debug - , lowercase , noticeDoc ) import Distribution.Types.CondTree @@ -143,6 +141,7 @@ import Distribution.Types.CondTree , traverseCondTreeA , traverseCondTreeV ) +import Distribution.Types.DumpBuildInfo (fromDumpBuildInfo) import Distribution.Types.SourceRepo (RepoType) import Distribution.Utils.NubList ( fromNubList @@ -156,7 +155,6 @@ import Distribution.Client.ParseUtils import Distribution.Client.ReplFlags (multiReplOption) import Distribution.Deprecated.ParseUtils ( PError (..) - , PWarning (..) , ParseResult (..) , commaNewLineListFieldParsec , newLineListField @@ -1714,91 +1712,47 @@ legacyPackageConfigFieldDescrs = (\v flags -> flags{configHcFlavor = v}) overrideDumpBuildInfo = - liftField - configDumpBuildInfo - (\v flags -> flags{configDumpBuildInfo = v}) - $ let name = "build-info" - in FieldDescr - name - ( \f -> case f of - Flag NoDumpBuildInfo -> Disp.text "False" - Flag DumpBuildInfo -> Disp.text "True" - _ -> Disp.empty - ) - ( \line str _ -> case () of - _ - | str == "False" -> ParseOk [] (Flag NoDumpBuildInfo) - | str == "True" -> ParseOk [] (Flag DumpBuildInfo) - | lstr == "false" -> ParseOk [caseWarning name] (Flag NoDumpBuildInfo) - | lstr == "true" -> ParseOk [caseWarning name] (Flag DumpBuildInfo) - | otherwise -> ParseFailed (NoParse name line) - where - lstr = lowercase str - ) - - -- TODO: [code cleanup] The following is a hack. The "optimization" and - -- "debug-info" fields are OptArg, and viewAsFieldDescr fails on that. - -- Instead of a hand-written parser and printer, we should handle this case - -- properly in the library. + liftField configDumpBuildInfo (\v flags -> flags{configDumpBuildInfo = v}) $ + let name = "build-info" + in FieldDescr + name + ( \case + NoFlag -> Disp.empty + Flag op -> Disp.text $ fromDumpBuildInfo op + ) + ( \line str _ -> case maybe NoFlag Flag (simpleParsec str) of + NoFlag -> ParseFailed (NoParse name line) + flag -> ParseOk [] flag + ) overrideFieldOptimization = - liftField - configOptimization - (\v flags -> flags{configOptimization = v}) - $ let name = "optimization" - in FieldDescr - name - ( \f -> case f of - Flag NoOptimisation -> Disp.text "False" - Flag NormalOptimisation -> Disp.text "True" - Flag MaximumOptimisation -> Disp.text "2" - _ -> Disp.empty - ) - ( \line str _ -> case () of - _ - | str == "False" -> ParseOk [] (Flag NoOptimisation) - | str == "True" -> ParseOk [] (Flag NormalOptimisation) - | str == "0" -> ParseOk [] (Flag NoOptimisation) - | str == "1" -> ParseOk [] (Flag NormalOptimisation) - | str == "2" -> ParseOk [] (Flag MaximumOptimisation) - | lstr == "false" -> ParseOk [caseWarning name] (Flag NoOptimisation) - | lstr == "true" -> ParseOk [caseWarning name] (Flag NormalOptimisation) - | otherwise -> ParseFailed (NoParse name line) - where - lstr = lowercase str - ) + liftField configOptimization (\v flags -> flags{configOptimization = v}) $ + let name = "optimization" + in FieldDescr + name + ( \case + NoFlag -> Disp.empty + flag -> Disp.text $ fromOptimisationLevel flag + ) + ( \line str _ -> case maybe NoFlag Flag (simpleParsec str) of + NoFlag -> ParseFailed (NoParse name line) + flag -> ParseOk [] flag + ) overrideFieldDebugInfo = liftField configDebugInfo (\v flags -> flags{configDebugInfo = v}) $ let name = "debug-info" in FieldDescr name - ( \f -> case f of - Flag NoDebugInfo -> Disp.text "False" - Flag MinimalDebugInfo -> Disp.text "1" - Flag NormalDebugInfo -> Disp.text "True" - Flag MaximalDebugInfo -> Disp.text "3" - _ -> Disp.empty + ( \case + NoFlag -> Disp.empty + flag -> Disp.text $ fromDebugInfoLevel flag ) - ( \line str _ -> case () of - _ - | str == "False" -> ParseOk [] (Flag NoDebugInfo) - | str == "True" -> ParseOk [] (Flag NormalDebugInfo) - | str == "0" -> ParseOk [] (Flag NoDebugInfo) - | str == "1" -> ParseOk [] (Flag MinimalDebugInfo) - | str == "2" -> ParseOk [] (Flag NormalDebugInfo) - | str == "3" -> ParseOk [] (Flag MaximalDebugInfo) - | lstr == "false" -> ParseOk [caseWarning name] (Flag NoDebugInfo) - | lstr == "true" -> ParseOk [caseWarning name] (Flag NormalDebugInfo) - | otherwise -> ParseFailed (NoParse name line) - where - lstr = lowercase str + ( \line str _ -> case maybe NoFlag Flag (simpleParsec str) of + NoFlag -> ParseFailed (NoParse name line) + flag -> ParseOk [] flag ) - caseWarning name = - PWarning $ - "The '" ++ name ++ "' field is case sensitive, use 'True' or 'False'." - prefixTest name | "test-" `isPrefixOf` name = name | otherwise = "test-" ++ name diff --git a/cabal-install/src/Distribution/Client/ProjectOrchestration.hs b/cabal-install/src/Distribution/Client/ProjectOrchestration.hs index 12718e4be5f..96ce4ba7b2f 100644 --- a/cabal-install/src/Distribution/Client/ProjectOrchestration.hs +++ b/cabal-install/src/Distribution/Client/ProjectOrchestration.hs @@ -183,10 +183,10 @@ import Distribution.Client.Errors import Distribution.Package import Distribution.Simple.Command (commandShowOptions) import Distribution.Simple.Compiler - ( OptimisationLevel (..) - , compilerCompatVersion + ( compilerCompatVersion , compilerId , compilerInfo + , fromOptimisationLevel , showCompilerId ) import Distribution.Simple.Configure (computeEffectiveProfiling) @@ -1257,13 +1257,7 @@ printPlan "Build profile: " ++ unwords [ "-w " ++ (showCompilerId . pkgConfigCompiler) elaboratedShared - , "-O" - ++ ( case globalOptimization <> localOptimization of -- if local is not set, read global - Setup.Flag NoOptimisation -> "0" - Setup.Flag NormalOptimisation -> "1" - Setup.Flag MaximumOptimisation -> "2" - Setup.NoFlag -> "1" - ) + , "-O" ++ fromOptimisationLevel (globalOptimization <> localOptimization) ] ++ "\n" diff --git a/changelog.d/11828.md b/changelog.d/11828.md new file mode 100644 index 00000000000..be9ddc26e5f --- /dev/null +++ b/changelog.d/11828.md @@ -0,0 +1,12 @@ +--- +synopsis: "Allow case insensitive bools and move to numeric render" +packages: [Cabal-syntax, Cabal, cabal-install] +prs: 11828 +--- +The `.cabal` file parser now accepts boolean values in a case‑insensitive manner (`true`, `True`, `TRUE`, `false`, etc.) without emitting a warning. +Previously only `True` and `False` were treated as “standard”, and other capitalisations triggered a parse warning. That warning was introduced in 2008 as a backwards‑compatibility shim to prevent Hackage uploads that would break very old Cabal versions. Since all supported Cabal releases can now handle case‑insensitive booleans, the warning has been removed as unnecessary. + +Additionally, the rendering of certain boolean‑like flags has been changed to use numeric levels: +- For the `-O` (optimisation) flag, `True` or an unspecified value now renders as `-O1`, while `False` renders as `-O0`. +- For the `-g` (debug info) flag, `True` or an unspecified value now renders `-g2`, while `False` renders as `-g0`. +This makes the displayed compiler flags more consistent with their internal semantics (e.g. optimisation level 1 is the default).