From 42cfcf6e93df3a1521a2d5a8952d96da3e7482d1 Mon Sep 17 00:00:00 2001 From: Greg Pfeil Date: Wed, 3 Dec 2025 23:07:22 -0700 Subject: [PATCH 1/2] Make `NoRecursion` optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Any dependency can introduce complexity when solving bounds. This gets `NeRecursion` out of the way automatically. 1. it introduces a new flag, `verify-no-recursion` that controls the use of `NoRecursion` and defaults to `True`; 2. if the solver can’t find a solution with the flag enabled, it will automatically try again with the flag disabled (that is, no dependency on `no-recursion`); 3. the local `cabal.project` file has `flags: +verify-no-recursion`, which prevents the solver from trying without the flag enabled, ensuring that local package development always has `NoRecursion` enabled, even if it causes the solver to fail. This also makes a few other minor changes: - Setup no longer uses `NoRecursion`, because it’s not possible to conditionalize it with the flag. - The `noisy-deprecations` flag now has `manual: True`, because disabling it won’t help the solver. - `custom-setup` has been moved above the `flag` sections because flags can’t apply to `custom-setup`. --- algebraic-graphs/Setup.hs | 1 - algebraic-graphs/algebraic-graph-duoids.cabal | 39 ++++++++++------- cabal.project | 5 +++ core/Setup.hs | 1 - core/duoids.cabal | 42 ++++++++++++------- hedgehog/Setup.hs | 1 - hedgehog/duoids-hedgehog.cabal | 42 ++++++++++++------- transformers/Setup.hs | 1 - transformers/duoidal-transformers.cabal | 42 ++++++++++++------- 9 files changed, 111 insertions(+), 63 deletions(-) diff --git a/algebraic-graphs/Setup.hs b/algebraic-graphs/Setup.hs index 621e81e..aee59ef 100644 --- a/algebraic-graphs/Setup.hs +++ b/algebraic-graphs/Setup.hs @@ -7,7 +7,6 @@ -- Warns even when `Unsafe` is explicit, not inferred. See -- https://gitlab.haskell.org/ghc/ghc/-/issues/16689 {-# OPTIONS_GHC -Wno-unsafe #-} -{-# OPTIONS_GHC -fplugin=NoRecursion #-} module Main (main) where diff --git a/algebraic-graphs/algebraic-graph-duoids.cabal b/algebraic-graphs/algebraic-graph-duoids.cabal index e1b0cb5..87b6246 100644 --- a/algebraic-graphs/algebraic-graph-duoids.cabal +++ b/algebraic-graphs/algebraic-graph-duoids.cabal @@ -37,17 +37,6 @@ source-repository head location: https://github.com/sellout/duoids.git subdir: algebraic-graphs -flag noisy-deprecations - description: - Prior to GHC 9.10, the @DEPRECATED@ pragma can’t distinguish between terms - and types. Consenquently, you can get spurious warnings when there’s a name - collision and the name in the other namespace is deprecated. Or you can - choose to not get those warnings, at the risk of not being warned when - there’s a name collision and the namespace you’re referencing is the one - that’s deprecated. - default: True - manual: False - custom-setup setup-depends: -- TODO: Due to haskell/cabal#3751, `Cabal` has to be specified even though @@ -58,7 +47,26 @@ custom-setup Cabal >= 3.0 && < 99, base ^>= {4.18.0, 4.19.0, 4.20.0, 4.21.0}, cabal-doctest ^>= {1.0.0}, - no-recursion ^>= {0.2.0, 0.3.0}, + +flag noisy-deprecations + description: + Prior to GHC 9.10, the @DEPRECATED@ pragma can’t distinguish between terms + and types. Consenquently, you can get spurious warnings when there’s a name + collision and the name in the other namespace is deprecated. Or you can + choose to not get those warnings, at the risk of not being warned when + there’s a name collision and the namespace you’re referencing is the one + that’s deprecated. + default: True + -- Because disabling this flag won’t help the solver. + manual: True + +flag verify-no-recursion + description: + By default, this will enable @NoRecursion@ during compilation. However, if + the solver can’t find a solution with @NoRecursion@, it will automatically + disable it. + default: True + manual: False -- This mimics the GHC2024 extension -- (https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/control.html?highlight=doandifthenelse#extension-GHC2024), @@ -83,7 +91,6 @@ common defaults import: GHC2024 build-depends: base ^>= {4.18.0, 4.19.0, 4.20.0, 4.21.0}, - no-recursion ^>= {0.2.0, 0.3.0}, ghc-options: -Weverything -- This one just reports unfixable things, AFAICT. @@ -93,7 +100,6 @@ common defaults -- Warns even when `Unsafe` is explicit, not inferred. See -- https://gitlab.haskell.org/ghc/ghc/-/issues/16689 -Wno-unsafe - -fplugin=NoRecursion if impl(ghc >= 9.8.1) ghc-options: -- Inference good. @@ -121,6 +127,11 @@ common defaults NoTypeApplications if flag(noisy-deprecations) cpp-options: -DSELLOUT_NOISY_DEPRECATIONS + if flag(verify-no-recursion) + build-depends: + no-recursion ^>= {0.2.0, 0.3.0}, + ghc-options: + -fplugin=NoRecursion library import: defaults diff --git a/cabal.project b/cabal.project index fb374cc..65d3cc6 100644 --- a/cabal.project +++ b/cabal.project @@ -17,6 +17,11 @@ constraints: -- 0.2 is the first version that allows @Safe@ disabling of no-recursion. no-recursion >= 0.2, +flags: + -- Ensure development of this package always uses @NoRecursion@, even if it + -- causes the solver to fail. + +verify-no-recursion + packages: ./core/duoids.cabal ./algebraic-graphs/algebraic-graph-duoids.cabal diff --git a/core/Setup.hs b/core/Setup.hs index 621e81e..aee59ef 100644 --- a/core/Setup.hs +++ b/core/Setup.hs @@ -7,7 +7,6 @@ -- Warns even when `Unsafe` is explicit, not inferred. See -- https://gitlab.haskell.org/ghc/ghc/-/issues/16689 {-# OPTIONS_GHC -Wno-unsafe #-} -{-# OPTIONS_GHC -fplugin=NoRecursion #-} module Main (main) where diff --git a/core/duoids.cabal b/core/duoids.cabal index 74bdec7..424ff24 100644 --- a/core/duoids.cabal +++ b/core/duoids.cabal @@ -38,17 +38,6 @@ source-repository head location: https://github.com/sellout/duoids.git subdir: core -flag noisy-deprecations - description: - Prior to GHC 9.10, the @DEPRECATED@ pragma can’t distinguish between terms - and types. Consenquently, you can get spurious warnings when there’s a name - collision and the name in the other namespace is deprecated. Or you can - choose to not get those warnings, at the risk of not being warned when - there’s a name collision and the namespace you’re referencing is the one - that’s deprecated. - default: True - manual: False - custom-setup setup-depends: -- TODO: Due to haskell/cabal#3751, `Cabal` has to be specified even though @@ -59,7 +48,26 @@ custom-setup Cabal >= 3.0 && < 99, base ^>= {4.18.0, 4.19.0, 4.20.0, 4.21.0}, cabal-doctest ^>= {1.0.0}, - no-recursion ^>= {0.2.0, 0.3.0}, + +flag noisy-deprecations + description: + Prior to GHC 9.10, the @DEPRECATED@ pragma can’t distinguish between terms + and types. Consenquently, you can get spurious warnings when there’s a name + collision and the name in the other namespace is deprecated. Or you can + choose to not get those warnings, at the risk of not being warned when + there’s a name collision and the namespace you’re referencing is the one + that’s deprecated. + default: True + -- Because disabling this flag won’t help the solver. + manual: True + +flag verify-no-recursion + description: + By default, this will enable @NoRecursion@ during compilation. However, if + the solver can’t find a solution with @NoRecursion@, it will automatically + disable it. + default: True + manual: False -- This mimics the GHC2024 extension -- (https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/control.html?highlight=doandifthenelse#extension-GHC2024), @@ -84,7 +92,6 @@ common defaults import: GHC2024 build-depends: base ^>= {4.18.0, 4.19.0, 4.20.0, 4.21.0}, - no-recursion ^>= {0.2.0, 0.3.0}, ghc-options: -Weverything -- This one just reports unfixable things, AFAICT. @@ -94,7 +101,6 @@ common defaults -- Warns even when `Unsafe` is explicit, not inferred. See -- https://gitlab.haskell.org/ghc/ghc/-/issues/16689 -Wno-unsafe - -fplugin=NoRecursion if impl(ghc >= 9.8.1) ghc-options: -- Inference good. @@ -121,7 +127,13 @@ common defaults NoStarIsType NoTypeApplications if flag(noisy-deprecations) - cpp-options: -DSELLOUT_NOISY_DEPRECATIONS + cpp-options: + -DSELLOUT_NOISY_DEPRECATIONS + if flag(verify-no-recursion) + build-depends: + no-recursion ^>= {0.2.0, 0.3.0}, + ghc-options: + -fplugin=NoRecursion library import: defaults diff --git a/hedgehog/Setup.hs b/hedgehog/Setup.hs index 621e81e..aee59ef 100644 --- a/hedgehog/Setup.hs +++ b/hedgehog/Setup.hs @@ -7,7 +7,6 @@ -- Warns even when `Unsafe` is explicit, not inferred. See -- https://gitlab.haskell.org/ghc/ghc/-/issues/16689 {-# OPTIONS_GHC -Wno-unsafe #-} -{-# OPTIONS_GHC -fplugin=NoRecursion #-} module Main (main) where diff --git a/hedgehog/duoids-hedgehog.cabal b/hedgehog/duoids-hedgehog.cabal index e61026f..7218b71 100644 --- a/hedgehog/duoids-hedgehog.cabal +++ b/hedgehog/duoids-hedgehog.cabal @@ -37,17 +37,6 @@ source-repository head location: https://github.com/sellout/duoids.git subdir: hedgehog -flag noisy-deprecations - description: - Prior to GHC 9.10, the @DEPRECATED@ pragma can’t distinguish between terms - and types. Consenquently, you can get spurious warnings when there’s a name - collision and the name in the other namespace is deprecated. Or you can - choose to not get those warnings, at the risk of not being warned when - there’s a name collision and the namespace you’re referencing is the one - that’s deprecated. - default: True - manual: False - custom-setup setup-depends: -- TODO: Due to haskell/cabal#3751, `Cabal` has to be specified even though @@ -58,7 +47,26 @@ custom-setup Cabal >= 3.0 && < 99, base ^>= {4.18.0, 4.19.0, 4.20.0, 4.21.0}, cabal-doctest ^>= {1.0.0}, - no-recursion ^>= {0.2.0, 0.3.0}, + +flag noisy-deprecations + description: + Prior to GHC 9.10, the @DEPRECATED@ pragma can’t distinguish between terms + and types. Consenquently, you can get spurious warnings when there’s a name + collision and the name in the other namespace is deprecated. Or you can + choose to not get those warnings, at the risk of not being warned when + there’s a name collision and the namespace you’re referencing is the one + that’s deprecated. + default: True + -- Because disabling this flag won’t help the solver. + manual: True + +flag verify-no-recursion + description: + By default, this will enable @NoRecursion@ during compilation. However, if + the solver can’t find a solution with @NoRecursion@, it will automatically + disable it. + default: True + manual: False -- This mimics the GHC2024 extension -- (https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/control.html?highlight=doandifthenelse#extension-GHC2024), @@ -83,7 +91,6 @@ common defaults import: GHC2024 build-depends: base ^>= {4.18.0, 4.19.0, 4.20.0, 4.21.0}, - no-recursion ^>= {0.2.0, 0.3.0}, ghc-options: -Weverything -- This one just reports unfixable things, AFAICT. @@ -93,7 +100,6 @@ common defaults -- Warns even when `Unsafe` is explicit, not inferred. See -- https://gitlab.haskell.org/ghc/ghc/-/issues/16689 -Wno-unsafe - -fplugin=NoRecursion if impl(ghc >= 9.8.1) ghc-options: -- Inference good. @@ -120,7 +126,13 @@ common defaults NoStarIsType NoTypeApplications if flag(noisy-deprecations) - cpp-options: -DSELLOUT_NOISY_DEPRECATIONS + cpp-options: + -DSELLOUT_NOISY_DEPRECATIONS + if flag(verify-no-recursion) + build-depends: + no-recursion ^>= {0.2.0, 0.3.0}, + ghc-options: + -fplugin=NoRecursion library import: defaults diff --git a/transformers/Setup.hs b/transformers/Setup.hs index 621e81e..aee59ef 100644 --- a/transformers/Setup.hs +++ b/transformers/Setup.hs @@ -7,7 +7,6 @@ -- Warns even when `Unsafe` is explicit, not inferred. See -- https://gitlab.haskell.org/ghc/ghc/-/issues/16689 {-# OPTIONS_GHC -Wno-unsafe #-} -{-# OPTIONS_GHC -fplugin=NoRecursion #-} module Main (main) where diff --git a/transformers/duoidal-transformers.cabal b/transformers/duoidal-transformers.cabal index 1fc21df..2736be7 100644 --- a/transformers/duoidal-transformers.cabal +++ b/transformers/duoidal-transformers.cabal @@ -37,17 +37,6 @@ source-repository head location: https://github.com/sellout/duoids.git subdir: transformers -flag noisy-deprecations - description: - Prior to GHC 9.10, the @DEPRECATED@ pragma can’t distinguish between terms - and types. Consenquently, you can get spurious warnings when there’s a name - collision and the name in the other namespace is deprecated. Or you can - choose to not get those warnings, at the risk of not being warned when - there’s a name collision and the namespace you’re referencing is the one - that’s deprecated. - default: True - manual: False - custom-setup setup-depends: -- TODO: Due to haskell/cabal#3751, `Cabal` has to be specified even though @@ -58,7 +47,26 @@ custom-setup Cabal >= 3.0 && < 99, base ^>= {4.18.0, 4.19.0, 4.20.0, 4.21.0}, cabal-doctest ^>= {1.0.0}, - no-recursion ^>= {0.2.0, 0.3.0}, + +flag noisy-deprecations + description: + Prior to GHC 9.10, the @DEPRECATED@ pragma can’t distinguish between terms + and types. Consenquently, you can get spurious warnings when there’s a name + collision and the name in the other namespace is deprecated. Or you can + choose to not get those warnings, at the risk of not being warned when + there’s a name collision and the namespace you’re referencing is the one + that’s deprecated. + default: True + -- Because disabling this flag won’t help the solver. + manual: True + +flag verify-no-recursion + description: + By default, this will enable @NoRecursion@ during compilation. However, if + the solver can’t find a solution with @NoRecursion@, it will automatically + disable it. + default: True + manual: False -- This mimics the GHC2024 extension -- (https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/control.html?highlight=doandifthenelse#extension-GHC2024), @@ -83,7 +91,6 @@ common defaults import: GHC2024 build-depends: base ^>= {4.18.0, 4.19.0, 4.20.0, 4.21.0}, - no-recursion ^>= {0.2.0, 0.3.0}, ghc-options: -Weverything -- This one just reports unfixable things, AFAICT. @@ -93,7 +100,6 @@ common defaults -- Warns even when `Unsafe` is explicit, not inferred. See -- https://gitlab.haskell.org/ghc/ghc/-/issues/16689 -Wno-unsafe - -fplugin=NoRecursion if impl(ghc >= 9.8.1) ghc-options: -- Inference good. @@ -120,7 +126,13 @@ common defaults NoStarIsType NoTypeApplications if flag(noisy-deprecations) - cpp-options: -DSELLOUT_NOISY_DEPRECATIONS + cpp-options: + -DSELLOUT_NOISY_DEPRECATIONS + if flag(verify-no-recursion) + build-depends: + no-recursion ^>= {0.2.0, 0.3.0}, + ghc-options: + -fplugin=NoRecursion library import: defaults From 1c20ea370e3c537784400c0ab71d8916ee2f46e4 Mon Sep 17 00:00:00 2001 From: Greg Pfeil Date: Thu, 4 Dec 2025 10:27:33 -0700 Subject: [PATCH 2/2] Default `verify-no-recursion` to `False` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s still enabled in cabal.project for local development, but this means consumers will never have to worry about it in their dependency graph. --- algebraic-graphs/algebraic-graph-duoids.cabal | 10 +++++----- cabal.project | 10 +++++----- core/duoids.cabal | 10 +++++----- hedgehog/duoids-hedgehog.cabal | 10 +++++----- transformers/duoidal-transformers.cabal | 10 +++++----- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/algebraic-graphs/algebraic-graph-duoids.cabal b/algebraic-graphs/algebraic-graph-duoids.cabal index 87b6246..6643439 100644 --- a/algebraic-graphs/algebraic-graph-duoids.cabal +++ b/algebraic-graphs/algebraic-graph-duoids.cabal @@ -62,11 +62,11 @@ flag noisy-deprecations flag verify-no-recursion description: - By default, this will enable @NoRecursion@ during compilation. However, if - the solver can’t find a solution with @NoRecursion@, it will automatically - disable it. - default: True - manual: False + Compile with "NoRecursion" enabled. This is intended for developers of this + package. + default: False + -- Because disabling this flag won’t help the solver. + manual: True -- This mimics the GHC2024 extension -- (https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/control.html?highlight=doandifthenelse#extension-GHC2024), diff --git a/cabal.project b/cabal.project index 65d3cc6..e3ba44a 100644 --- a/cabal.project +++ b/cabal.project @@ -5,6 +5,11 @@ max-backjumps: -1 minimize-conflict-set: true reorder-goals: true +flags: + -- Ensure development of this project always uses @NoRecursion@, even if it + -- causes the solver to fail. + +verify-no-recursion + program-options ghc-options: -Werror @@ -17,11 +22,6 @@ constraints: -- 0.2 is the first version that allows @Safe@ disabling of no-recursion. no-recursion >= 0.2, -flags: - -- Ensure development of this package always uses @NoRecursion@, even if it - -- causes the solver to fail. - +verify-no-recursion - packages: ./core/duoids.cabal ./algebraic-graphs/algebraic-graph-duoids.cabal diff --git a/core/duoids.cabal b/core/duoids.cabal index 424ff24..3ab7cc9 100644 --- a/core/duoids.cabal +++ b/core/duoids.cabal @@ -63,11 +63,11 @@ flag noisy-deprecations flag verify-no-recursion description: - By default, this will enable @NoRecursion@ during compilation. However, if - the solver can’t find a solution with @NoRecursion@, it will automatically - disable it. - default: True - manual: False + Compile with "NoRecursion" enabled. This is intended for developers of this + package. + default: False + -- Because disabling this flag won’t help the solver. + manual: True -- This mimics the GHC2024 extension -- (https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/control.html?highlight=doandifthenelse#extension-GHC2024), diff --git a/hedgehog/duoids-hedgehog.cabal b/hedgehog/duoids-hedgehog.cabal index 7218b71..10340db 100644 --- a/hedgehog/duoids-hedgehog.cabal +++ b/hedgehog/duoids-hedgehog.cabal @@ -62,11 +62,11 @@ flag noisy-deprecations flag verify-no-recursion description: - By default, this will enable @NoRecursion@ during compilation. However, if - the solver can’t find a solution with @NoRecursion@, it will automatically - disable it. - default: True - manual: False + Compile with "NoRecursion" enabled. This is intended for developers of this + package. + default: False + -- Because disabling this flag won’t help the solver. + manual: True -- This mimics the GHC2024 extension -- (https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/control.html?highlight=doandifthenelse#extension-GHC2024), diff --git a/transformers/duoidal-transformers.cabal b/transformers/duoidal-transformers.cabal index 2736be7..06a0bfb 100644 --- a/transformers/duoidal-transformers.cabal +++ b/transformers/duoidal-transformers.cabal @@ -62,11 +62,11 @@ flag noisy-deprecations flag verify-no-recursion description: - By default, this will enable @NoRecursion@ during compilation. However, if - the solver can’t find a solution with @NoRecursion@, it will automatically - disable it. - default: True - manual: False + Compile with "NoRecursion" enabled. This is intended for developers of this + package. + default: False + -- Because disabling this flag won’t help the solver. + manual: True -- This mimics the GHC2024 extension -- (https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/control.html?highlight=doandifthenelse#extension-GHC2024),