From 4f24ed6e3255883ead6281bb7463e0bb83880479 Mon Sep 17 00:00:00 2001 From: Ilia Baryshnikov Date: Fri, 5 Jun 2026 19:25:03 +0300 Subject: [PATCH 1/2] Allow case insensitive bools --- Cabal-syntax/src/Distribution/Parsec.hs | 9 ++----- .../src/Distribution/Parsec/Warning.hs | 2 -- Cabal-tests/tests/ParserTests.hs | 1 - .../tests/ParserTests/warnings/bool.cabal | 12 --------- .../src/Distribution/Client/Config.hs | 26 +++---------------- .../Client/ProjectConfig/Legacy.hs | 23 +++++----------- changelog.d/11828.md | 7 +++++ 7 files changed, 19 insertions(+), 61 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 4420b3954f3..ddccdbac5d0 100644 --- a/Cabal-syntax/src/Distribution/Parsec.hs +++ b/Cabal-syntax/src/Distribution/Parsec.hs @@ -60,7 +60,6 @@ module Distribution.Parsec import Data.ByteString (ByteString) import Data.Char (digitToInt, intToDigit) -import Data.Functor (($>)) import Data.List (transpose) import Distribution.CabalSpecVersion import Distribution.Compat.Prelude @@ -251,15 +250,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 $> True - | lstr == "false" = parsecWarning PWTBoolCase caseWarning $> 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 8ded62cdb6e..d18187be062 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-install/src/Distribution/Client/Config.hs b/cabal-install/src/Distribution/Client/Config.hs index 506eb74d1c8..488f3871562 100644 --- a/cabal-install/src/Distribution/Client/Config.hs +++ b/cabal-install/src/Distribution/Client/Config.hs @@ -135,7 +135,6 @@ import Distribution.Compiler import Distribution.Deprecated.ParseUtils ( FieldDescr (..) , PError (..) - , PWarning (..) , ParseResult (..) , liftField , lineNo @@ -1203,24 +1202,14 @@ configFieldDescriptions src = ) ( \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) + | lstr == "false" -> ParseOk [] (Flag NoOptimisation) + | lstr == "true" -> ParseOk [] (Flag NormalOptimisation) | otherwise -> ParseFailed (NoParse name line) where lstr = lowercase str - caseWarning = - PWarning $ - "The '" - ++ name - ++ "' field is case sensitive, use 'True' or 'False'." ) , liftField configDebugInfo (\v flags -> flags{configDebugInfo = v}) $ let name = "debug-info" @@ -1235,22 +1224,15 @@ configFieldDescriptions src = ) ( \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) + | lstr == "false" -> ParseOk [] (Flag NoDebugInfo) + | lstr == "true" -> ParseOk [] (Flag NormalDebugInfo) | otherwise -> ParseFailed (NoParse name line) where lstr = lowercase str - caseWarning = - PWarning $ - "The '" - ++ name - ++ "' field is case sensitive, use 'True' or 'False'." ) ] ++ toSavedConfig diff --git a/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs b/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs index eb243ae4e07..74e583f689f 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs @@ -157,7 +157,6 @@ import Distribution.Client.ParseUtils import Distribution.Client.ReplFlags (multiReplOption) import Distribution.Deprecated.ParseUtils ( PError (..) - , PWarning (..) , ParseResult (..) , commaNewLineListFieldParsec , newLineListField @@ -1692,10 +1691,8 @@ legacyPackageConfigFieldDescrs = ) ( \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) + | lstr == "false" -> ParseOk [] (Flag NoDumpBuildInfo) + | lstr == "true" -> ParseOk [] (Flag DumpBuildInfo) | otherwise -> ParseFailed (NoParse name line) where lstr = lowercase str @@ -1721,13 +1718,11 @@ legacyPackageConfigFieldDescrs = ) ( \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) + | lstr == "false" -> ParseOk [] (Flag NoOptimisation) + | lstr == "true" -> ParseOk [] (Flag NormalOptimisation) | otherwise -> ParseFailed (NoParse name line) where lstr = lowercase str @@ -1747,23 +1742,17 @@ legacyPackageConfigFieldDescrs = ) ( \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) + | lstr == "false" -> ParseOk [] (Flag NoDebugInfo) + | lstr == "true" -> ParseOk [] (Flag NormalDebugInfo) | otherwise -> ParseFailed (NoParse name line) where lstr = lowercase str ) - 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/changelog.d/11828.md b/changelog.d/11828.md new file mode 100644 index 00000000000..20a009412f1 --- /dev/null +++ b/changelog.d/11828.md @@ -0,0 +1,7 @@ +--- +synopsis: "Allow case insensitive bools" +packages: [Cabal-syntax, 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. From 1f17fbae055ef35e45322b12dd0e1142851f00d6 Mon Sep 17 00:00:00 2001 From: Ilia Baryshnikov Date: Fri, 19 Jun 2026 13:41:14 +0300 Subject: [PATCH 2/2] add warning bools test --- .../ProjectConfig/FlagsBools/cabal.out | 8 ++++++ .../ProjectConfig/FlagsBools/cabal.project | 8 ++++++ .../ProjectConfig/FlagsBools/cabal.test.hs | 4 +++ .../ProjectConfig/FlagsBools/test.cabal | 26 +++++++++++++++++++ 4 files changed, 46 insertions(+) create mode 100644 cabal-testsuite/PackageTests/ProjectConfig/FlagsBools/cabal.out create mode 100644 cabal-testsuite/PackageTests/ProjectConfig/FlagsBools/cabal.project create mode 100644 cabal-testsuite/PackageTests/ProjectConfig/FlagsBools/cabal.test.hs create mode 100644 cabal-testsuite/PackageTests/ProjectConfig/FlagsBools/test.cabal diff --git a/cabal-testsuite/PackageTests/ProjectConfig/FlagsBools/cabal.out b/cabal-testsuite/PackageTests/ProjectConfig/FlagsBools/cabal.out new file mode 100644 index 00000000000..b9929ed847c --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectConfig/FlagsBools/cabal.out @@ -0,0 +1,8 @@ +# cabal build +Resolving dependencies... +Build profile: -w ghc- -O1 +In order, the following will be built: + - test-0.1 (lib) (first run) +Configuring library for test-0.1... +Preprocessing library for test-0.1... +Building library for test-0.1... diff --git a/cabal-testsuite/PackageTests/ProjectConfig/FlagsBools/cabal.project b/cabal-testsuite/PackageTests/ProjectConfig/FlagsBools/cabal.project new file mode 100644 index 00000000000..84e7456eccf --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectConfig/FlagsBools/cabal.project @@ -0,0 +1,8 @@ +packages: . + +build-info: true +optimization: tRuE + +package test + flags: -bar + flags: -baz diff --git a/cabal-testsuite/PackageTests/ProjectConfig/FlagsBools/cabal.test.hs b/cabal-testsuite/PackageTests/ProjectConfig/FlagsBools/cabal.test.hs new file mode 100644 index 00000000000..db6203e6546 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectConfig/FlagsBools/cabal.test.hs @@ -0,0 +1,4 @@ +import Test.Cabal.Prelude + +main = cabalTest $ do + cabal "build" [] diff --git a/cabal-testsuite/PackageTests/ProjectConfig/FlagsBools/test.cabal b/cabal-testsuite/PackageTests/ProjectConfig/FlagsBools/test.cabal new file mode 100644 index 00000000000..a7f68d6390f --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectConfig/FlagsBools/test.cabal @@ -0,0 +1,26 @@ +cabal-version: 3.0 +name: test +version: 0.1 +license: BSD-3-Clause +build-type: Simple + +flag bar + default: true + manual: True + +flag baz + default: TRUE + manual: True + +flag quux + default: false + manual: False + +flag quuux + default: FALSE + manual: false + +Library + default-language: Haskell2010 + if flag(bar) || flag (baz) + buildable: false