From e37c267c66413cd4999b3ca84c1baec7af22e7ba 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 eeb11138209..752e5f5b1ee 100644 --- a/Cabal-syntax/src/Distribution/Parsec.hs +++ b/Cabal-syntax/src/Distribution/Parsec.hs @@ -56,7 +56,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 @@ -247,15 +246,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 93e866c2f26..3c3111914cc 100644 --- a/Cabal-syntax/src/Distribution/Parsec/Warning.hs +++ b/Cabal-syntax/src/Distribution/Parsec/Warning.hs @@ -22,8 +22,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 c4c5a5dfba5..03c6fd87652 100644 --- a/cabal-install/src/Distribution/Client/Config.hs +++ b/cabal-install/src/Distribution/Client/Config.hs @@ -134,7 +134,6 @@ import Distribution.Compiler import Distribution.Deprecated.ParseUtils ( FieldDescr (..) , PError (..) - , PWarning (..) , ParseResult (..) , liftField , lineNo @@ -1202,24 +1201,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" @@ -1234,22 +1223,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 bf47efd8a2e..fe39c8a23e0 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs @@ -153,7 +153,6 @@ import Distribution.Client.ParseUtils import Distribution.Client.ReplFlags (multiReplOption) import Distribution.Deprecated.ParseUtils ( PError (..) - , PWarning (..) , ParseResult (..) , commaNewLineListFieldParsec , newLineListField @@ -1688,10 +1687,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 @@ -1717,13 +1714,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 @@ -1743,23 +1738,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 efe5a4afdf0e532561c536b6cff74a237b3c05a8 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