From 2af8b64753a01c7ef0a714464520979134e62763 Mon Sep 17 00:00:00 2001 From: Mike Pilgrem Date: Sat, 9 May 2026 19:02:15 +0100 Subject: [PATCH] Fix #6905 Clear call stack in addFinal --- ChangeLog.md | 4 +++ src/Stack/Build/ConstructPlan.hs | 8 +++++- .../tests/6905-cyclic-plan/Main.hs | 27 +++++++++++++++++++ .../files/.gitignore | 3 ++- .../files/myPackageA/package.yaml | 11 ++++++++ .../files/myPackageA/src/LibA.hs | 5 ++++ .../files/myPackageB/package.yaml | 3 +-- .../files/myPackageB/src/LibB.hs | 0 .../files/myPackageB/test/Main.hs | 0 .../files/myPackageC/package.yaml | 16 +++++++++++ .../files/myPackageC/src/LibC.hs | 6 +++++ .../files/myPackageC/test/Main.hs | 4 +++ .../files/myPackageD/package.yaml | 11 ++++++++ .../files/myPackageD/src/LibD.hs | 5 ++++ .../tests/6905-cyclic-plan/files/stack1.yaml | 5 ++++ .../tests/6905-cyclic-plan/files/stack2.yaml | 5 ++++ .../{multi-test => 6905-multi-test}/Main.hs | 12 +++------ .../tests/6905-multi-test/files/.gitignore | 6 +++++ .../files/myPackageA/app/Main.hs | 0 .../files/myPackageA/package.yaml | 3 +-- .../files/myPackageA/src/LibA.hs | 0 .../files/myPackageA/test1/Main.hs | 0 .../files/myPackageA/test2/Main.hs | 0 .../files/myPackageA/test3/Main.hs | 0 .../files/myPackageB/package.yaml | 16 +++++++++++ .../files/myPackageB/src/LibB.hs | 6 +++++ .../files/myPackageB/test/Main.hs | 4 +++ .../files/myPackageC/app/Main.hs | 0 .../files/myPackageC/package.yaml | 0 .../files/myPackageC/src/LibC.hs | 0 .../files/myPackageC/test/Main.hs | 0 .../files/stack.yaml | 0 32 files changed, 145 insertions(+), 15 deletions(-) create mode 100644 tests/integration/tests/6905-cyclic-plan/Main.hs rename tests/integration/tests/{multi-test => 6905-cyclic-plan}/files/.gitignore (50%) create mode 100644 tests/integration/tests/6905-cyclic-plan/files/myPackageA/package.yaml create mode 100644 tests/integration/tests/6905-cyclic-plan/files/myPackageA/src/LibA.hs rename tests/integration/tests/{multi-test => 6905-cyclic-plan}/files/myPackageB/package.yaml (63%) rename tests/integration/tests/{multi-test => 6905-cyclic-plan}/files/myPackageB/src/LibB.hs (100%) rename tests/integration/tests/{multi-test => 6905-cyclic-plan}/files/myPackageB/test/Main.hs (100%) create mode 100644 tests/integration/tests/6905-cyclic-plan/files/myPackageC/package.yaml create mode 100644 tests/integration/tests/6905-cyclic-plan/files/myPackageC/src/LibC.hs create mode 100644 tests/integration/tests/6905-cyclic-plan/files/myPackageC/test/Main.hs create mode 100644 tests/integration/tests/6905-cyclic-plan/files/myPackageD/package.yaml create mode 100644 tests/integration/tests/6905-cyclic-plan/files/myPackageD/src/LibD.hs create mode 100644 tests/integration/tests/6905-cyclic-plan/files/stack1.yaml create mode 100644 tests/integration/tests/6905-cyclic-plan/files/stack2.yaml rename tests/integration/tests/{multi-test => 6905-multi-test}/Main.hs (71%) create mode 100644 tests/integration/tests/6905-multi-test/files/.gitignore rename tests/integration/tests/{multi-test => 6905-multi-test}/files/myPackageA/app/Main.hs (100%) rename tests/integration/tests/{multi-test => 6905-multi-test}/files/myPackageA/package.yaml (82%) rename tests/integration/tests/{multi-test => 6905-multi-test}/files/myPackageA/src/LibA.hs (100%) rename tests/integration/tests/{multi-test => 6905-multi-test}/files/myPackageA/test1/Main.hs (100%) rename tests/integration/tests/{multi-test => 6905-multi-test}/files/myPackageA/test2/Main.hs (100%) rename tests/integration/tests/{multi-test => 6905-multi-test}/files/myPackageA/test3/Main.hs (100%) create mode 100644 tests/integration/tests/6905-multi-test/files/myPackageB/package.yaml create mode 100644 tests/integration/tests/6905-multi-test/files/myPackageB/src/LibB.hs create mode 100644 tests/integration/tests/6905-multi-test/files/myPackageB/test/Main.hs rename tests/integration/tests/{multi-test => 6905-multi-test}/files/myPackageC/app/Main.hs (100%) rename tests/integration/tests/{multi-test => 6905-multi-test}/files/myPackageC/package.yaml (100%) rename tests/integration/tests/{multi-test => 6905-multi-test}/files/myPackageC/src/LibC.hs (100%) rename tests/integration/tests/{multi-test => 6905-multi-test}/files/myPackageC/test/Main.hs (100%) rename tests/integration/tests/{multi-test => 6905-multi-test}/files/stack.yaml (100%) diff --git a/ChangeLog.md b/ChangeLog.md index ea5760e3c1..438070e61a 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -51,6 +51,10 @@ Bug fixes: * After March 2026, Hackage requires Stack's user agent to be set when applying digest authentication to a request. Stack's `upload` command now does that, re-establishing authentication by Hackage username and password. +* Stack 3.9.3 and earlier fail to construct a build plan if project package A + depends on project package B and package B's executables (only) depend on + package A and the name of A is before that of B, alphabetically. That bug is + fixed. ## v3.9.3 - 2026-02-19 diff --git a/src/Stack/Build/ConstructPlan.hs b/src/Stack/Build/ConstructPlan.hs index 5b9388a64d..37959fe739 100644 --- a/src/Stack/Build/ConstructPlan.hs +++ b/src/Stack/Build/ConstructPlan.hs @@ -483,7 +483,9 @@ addFinal :: -> M () addFinal lp package allInOne buildHaddocks = do let name = package.name - res <- addPackageDeps package >>= \case + logDebugPlanS "addFinal" "Clearing the call stack." + res <- local (\ctx' -> ctx' { callStack = [] }) $ + addPackageDeps package >>= \case Left e -> pure $ Left e Right (MissingPresentDeps missing present _minLoc) -> do let pkgConfigOpts = packageConfigureOptsFromPackage package @@ -505,6 +507,10 @@ addFinal lp package allInOne buildHaddocks = do , cachePkgSrc = CacheSrcLocal (toFilePath (parent lp.cabalFP)) , buildTypeConfig = packageBuildTypeConfig package } + ctx <- ask + logDebugPlanS "addFinal" $ + "Restoring the call stack: " + <> fromString (show $ map packageNameString ctx.callStack) logDebugPlanS "addFinal" $ "Adding to construction output " <> fromPackageName name diff --git a/tests/integration/tests/6905-cyclic-plan/Main.hs b/tests/integration/tests/6905-cyclic-plan/Main.hs new file mode 100644 index 0000000000..75120e5d06 --- /dev/null +++ b/tests/integration/tests/6905-cyclic-plan/Main.hs @@ -0,0 +1,27 @@ +-- | The test's project has project packages A and B. +-- +-- In terms of main libraries, the dependencies are (->- is 'depends on'): +-- +-- A ->- B +-- +-- In terms of executables (a test suite): +-- +-- B ->- A +-- +-- As, overall, A ->- B and B ->- A, packages A and B cannot be built +-- 'all-in-one'. +-- +-- This integration test tests: +-- +-- * when A is named myPackageA and B is named myPackageB; and +-- +-- * when A is named myPackageD and B is named myPackageC. +-- +-- See: https://github.com/commercialhaskell/stack/issues/6905 + +import StackTest + +main :: IO () +main = do + stack ["--stack-yaml", "stack1.yaml", "test"] + stack ["--stack-yaml", "stack2.yaml", "test"] diff --git a/tests/integration/tests/multi-test/files/.gitignore b/tests/integration/tests/6905-cyclic-plan/files/.gitignore similarity index 50% rename from tests/integration/tests/multi-test/files/.gitignore rename to tests/integration/tests/6905-cyclic-plan/files/.gitignore index 0f3e4a815f..5087095541 100644 --- a/tests/integration/tests/multi-test/files/.gitignore +++ b/tests/integration/tests/6905-cyclic-plan/files/.gitignore @@ -1,3 +1,4 @@ myPackageA.cabal +myPackageB.cabal myPackageC.cabal -0myPackageB.cabal +myPackageD.cabal diff --git a/tests/integration/tests/6905-cyclic-plan/files/myPackageA/package.yaml b/tests/integration/tests/6905-cyclic-plan/files/myPackageA/package.yaml new file mode 100644 index 0000000000..bb7167768b --- /dev/null +++ b/tests/integration/tests/6905-cyclic-plan/files/myPackageA/package.yaml @@ -0,0 +1,11 @@ +spec-version: 0.36.0 + +name: myPackageA + +dependencies: +- base + +library: + source-dirs: src + dependencies: + - myPackageB diff --git a/tests/integration/tests/6905-cyclic-plan/files/myPackageA/src/LibA.hs b/tests/integration/tests/6905-cyclic-plan/files/myPackageA/src/LibA.hs new file mode 100644 index 0000000000..743d4bf8d0 --- /dev/null +++ b/tests/integration/tests/6905-cyclic-plan/files/myPackageA/src/LibA.hs @@ -0,0 +1,5 @@ +module LibA + ( funcB + ) where + +import LibB ( funcB ) diff --git a/tests/integration/tests/multi-test/files/myPackageB/package.yaml b/tests/integration/tests/6905-cyclic-plan/files/myPackageB/package.yaml similarity index 63% rename from tests/integration/tests/multi-test/files/myPackageB/package.yaml rename to tests/integration/tests/6905-cyclic-plan/files/myPackageB/package.yaml index 202a258230..c5d19b86c3 100644 --- a/tests/integration/tests/multi-test/files/myPackageB/package.yaml +++ b/tests/integration/tests/6905-cyclic-plan/files/myPackageB/package.yaml @@ -1,7 +1,6 @@ spec-version: 0.36.0 -# Only builds if this package name comes before myPackageA, alphabetically! -name: 0myPackageB +name: myPackageB dependencies: - base diff --git a/tests/integration/tests/multi-test/files/myPackageB/src/LibB.hs b/tests/integration/tests/6905-cyclic-plan/files/myPackageB/src/LibB.hs similarity index 100% rename from tests/integration/tests/multi-test/files/myPackageB/src/LibB.hs rename to tests/integration/tests/6905-cyclic-plan/files/myPackageB/src/LibB.hs diff --git a/tests/integration/tests/multi-test/files/myPackageB/test/Main.hs b/tests/integration/tests/6905-cyclic-plan/files/myPackageB/test/Main.hs similarity index 100% rename from tests/integration/tests/multi-test/files/myPackageB/test/Main.hs rename to tests/integration/tests/6905-cyclic-plan/files/myPackageB/test/Main.hs diff --git a/tests/integration/tests/6905-cyclic-plan/files/myPackageC/package.yaml b/tests/integration/tests/6905-cyclic-plan/files/myPackageC/package.yaml new file mode 100644 index 0000000000..89dfd7f40b --- /dev/null +++ b/tests/integration/tests/6905-cyclic-plan/files/myPackageC/package.yaml @@ -0,0 +1,16 @@ +spec-version: 0.36.0 + +name: myPackageC + +dependencies: +- base + +library: + source-dirs: src + +tests: + test: + source-dirs: test + main: Main.hs + dependencies: + - myPackageD diff --git a/tests/integration/tests/6905-cyclic-plan/files/myPackageC/src/LibC.hs b/tests/integration/tests/6905-cyclic-plan/files/myPackageC/src/LibC.hs new file mode 100644 index 0000000000..28474cddd5 --- /dev/null +++ b/tests/integration/tests/6905-cyclic-plan/files/myPackageC/src/LibC.hs @@ -0,0 +1,6 @@ +module LibC + ( funcC + ) where + +funcC :: IO () +funcC = pure () diff --git a/tests/integration/tests/6905-cyclic-plan/files/myPackageC/test/Main.hs b/tests/integration/tests/6905-cyclic-plan/files/myPackageC/test/Main.hs new file mode 100644 index 0000000000..c438615556 --- /dev/null +++ b/tests/integration/tests/6905-cyclic-plan/files/myPackageC/test/Main.hs @@ -0,0 +1,4 @@ +import LibD ( funcC ) + +main :: IO () +main = funcC diff --git a/tests/integration/tests/6905-cyclic-plan/files/myPackageD/package.yaml b/tests/integration/tests/6905-cyclic-plan/files/myPackageD/package.yaml new file mode 100644 index 0000000000..1d913ac5ef --- /dev/null +++ b/tests/integration/tests/6905-cyclic-plan/files/myPackageD/package.yaml @@ -0,0 +1,11 @@ +spec-version: 0.36.0 + +name: myPackageD + +dependencies: +- base + +library: + source-dirs: src + dependencies: + - myPackageC diff --git a/tests/integration/tests/6905-cyclic-plan/files/myPackageD/src/LibD.hs b/tests/integration/tests/6905-cyclic-plan/files/myPackageD/src/LibD.hs new file mode 100644 index 0000000000..481d4e7f69 --- /dev/null +++ b/tests/integration/tests/6905-cyclic-plan/files/myPackageD/src/LibD.hs @@ -0,0 +1,5 @@ +module LibD + ( funcC + ) where + +import LibC ( funcC ) diff --git a/tests/integration/tests/6905-cyclic-plan/files/stack1.yaml b/tests/integration/tests/6905-cyclic-plan/files/stack1.yaml new file mode 100644 index 0000000000..68891a8d7c --- /dev/null +++ b/tests/integration/tests/6905-cyclic-plan/files/stack1.yaml @@ -0,0 +1,5 @@ +snapshot: ghc-9.10.3 + +packages: +- myPackageA +- myPackageB diff --git a/tests/integration/tests/6905-cyclic-plan/files/stack2.yaml b/tests/integration/tests/6905-cyclic-plan/files/stack2.yaml new file mode 100644 index 0000000000..740f730a48 --- /dev/null +++ b/tests/integration/tests/6905-cyclic-plan/files/stack2.yaml @@ -0,0 +1,5 @@ +snapshot: ghc-9.10.3 + +packages: +- myPackageC +- myPackageD diff --git a/tests/integration/tests/multi-test/Main.hs b/tests/integration/tests/6905-multi-test/Main.hs similarity index 71% rename from tests/integration/tests/multi-test/Main.hs rename to tests/integration/tests/6905-multi-test/Main.hs index 32853b1673..2e21e47b41 100644 --- a/tests/integration/tests/multi-test/Main.hs +++ b/tests/integration/tests/6905-multi-test/Main.hs @@ -11,9 +11,9 @@ -- As, overall, A ->- B and B ->- A, packages A and B cannot be built -- 'all-in-one'. -- --- This integration test passes when A is named myPackageA and B is named --- 0myPackageB, but it fails when B is renamed myPackageB. That must be a bug in --- Stack. +-- A, B and C are named myPackageA, myPackageB and myPackageC respectively. +-- +-- See: https://github.com/commercialhaskell/stack/issues/6905 import Control.Monad ( unless ) import Data.List ( isInfixOf ) @@ -21,14 +21,8 @@ import StackTest main :: IO () main = do - -- FIXME: Make 'clean' unnecessary (see #1411) - stack ["clean"] stackCheckStderr ["test", "--coverage"] $ \out -> do unless ("The coverage report for myPackageA's test-suite test1 is available at" `isInfixOf` out) $ fail "Didn't get expected report for test1" unless ("[S-6829]" `isInfixOf` out) $ fail "Didn't get expected empty report for test2" - -- Test then build works too. - stack ["clean"] - stack ["test"] - stack ["build"] diff --git a/tests/integration/tests/6905-multi-test/files/.gitignore b/tests/integration/tests/6905-multi-test/files/.gitignore new file mode 100644 index 0000000000..03e2c6587b --- /dev/null +++ b/tests/integration/tests/6905-multi-test/files/.gitignore @@ -0,0 +1,6 @@ +myPackageA.cabal +myPackageB.cabal +myPackageC.cabal +myPackageD.cabal +myPackageE.cabal +myPackageF.cabal diff --git a/tests/integration/tests/multi-test/files/myPackageA/app/Main.hs b/tests/integration/tests/6905-multi-test/files/myPackageA/app/Main.hs similarity index 100% rename from tests/integration/tests/multi-test/files/myPackageA/app/Main.hs rename to tests/integration/tests/6905-multi-test/files/myPackageA/app/Main.hs diff --git a/tests/integration/tests/multi-test/files/myPackageA/package.yaml b/tests/integration/tests/6905-multi-test/files/myPackageA/package.yaml similarity index 82% rename from tests/integration/tests/multi-test/files/myPackageA/package.yaml rename to tests/integration/tests/6905-multi-test/files/myPackageA/package.yaml index 7811ddfd05..d246bd23b8 100644 --- a/tests/integration/tests/multi-test/files/myPackageA/package.yaml +++ b/tests/integration/tests/6905-multi-test/files/myPackageA/package.yaml @@ -8,8 +8,7 @@ dependencies: library: source-dirs: src dependencies: - # Only builds if this package name comes before myPackageA, alphabetically! - - 0myPackageB + - myPackageB executables: myExeA: diff --git a/tests/integration/tests/multi-test/files/myPackageA/src/LibA.hs b/tests/integration/tests/6905-multi-test/files/myPackageA/src/LibA.hs similarity index 100% rename from tests/integration/tests/multi-test/files/myPackageA/src/LibA.hs rename to tests/integration/tests/6905-multi-test/files/myPackageA/src/LibA.hs diff --git a/tests/integration/tests/multi-test/files/myPackageA/test1/Main.hs b/tests/integration/tests/6905-multi-test/files/myPackageA/test1/Main.hs similarity index 100% rename from tests/integration/tests/multi-test/files/myPackageA/test1/Main.hs rename to tests/integration/tests/6905-multi-test/files/myPackageA/test1/Main.hs diff --git a/tests/integration/tests/multi-test/files/myPackageA/test2/Main.hs b/tests/integration/tests/6905-multi-test/files/myPackageA/test2/Main.hs similarity index 100% rename from tests/integration/tests/multi-test/files/myPackageA/test2/Main.hs rename to tests/integration/tests/6905-multi-test/files/myPackageA/test2/Main.hs diff --git a/tests/integration/tests/multi-test/files/myPackageA/test3/Main.hs b/tests/integration/tests/6905-multi-test/files/myPackageA/test3/Main.hs similarity index 100% rename from tests/integration/tests/multi-test/files/myPackageA/test3/Main.hs rename to tests/integration/tests/6905-multi-test/files/myPackageA/test3/Main.hs diff --git a/tests/integration/tests/6905-multi-test/files/myPackageB/package.yaml b/tests/integration/tests/6905-multi-test/files/myPackageB/package.yaml new file mode 100644 index 0000000000..c5d19b86c3 --- /dev/null +++ b/tests/integration/tests/6905-multi-test/files/myPackageB/package.yaml @@ -0,0 +1,16 @@ +spec-version: 0.36.0 + +name: myPackageB + +dependencies: +- base + +library: + source-dirs: src + +tests: + test: + source-dirs: test + main: Main.hs + dependencies: + - myPackageA diff --git a/tests/integration/tests/6905-multi-test/files/myPackageB/src/LibB.hs b/tests/integration/tests/6905-multi-test/files/myPackageB/src/LibB.hs new file mode 100644 index 0000000000..e714f965fe --- /dev/null +++ b/tests/integration/tests/6905-multi-test/files/myPackageB/src/LibB.hs @@ -0,0 +1,6 @@ +module LibB + ( funcB + ) where + +funcB :: IO () +funcB = pure () diff --git a/tests/integration/tests/6905-multi-test/files/myPackageB/test/Main.hs b/tests/integration/tests/6905-multi-test/files/myPackageB/test/Main.hs new file mode 100644 index 0000000000..e7c27dd1be --- /dev/null +++ b/tests/integration/tests/6905-multi-test/files/myPackageB/test/Main.hs @@ -0,0 +1,4 @@ +import LibA ( funcB ) + +main :: IO () +main = funcB diff --git a/tests/integration/tests/multi-test/files/myPackageC/app/Main.hs b/tests/integration/tests/6905-multi-test/files/myPackageC/app/Main.hs similarity index 100% rename from tests/integration/tests/multi-test/files/myPackageC/app/Main.hs rename to tests/integration/tests/6905-multi-test/files/myPackageC/app/Main.hs diff --git a/tests/integration/tests/multi-test/files/myPackageC/package.yaml b/tests/integration/tests/6905-multi-test/files/myPackageC/package.yaml similarity index 100% rename from tests/integration/tests/multi-test/files/myPackageC/package.yaml rename to tests/integration/tests/6905-multi-test/files/myPackageC/package.yaml diff --git a/tests/integration/tests/multi-test/files/myPackageC/src/LibC.hs b/tests/integration/tests/6905-multi-test/files/myPackageC/src/LibC.hs similarity index 100% rename from tests/integration/tests/multi-test/files/myPackageC/src/LibC.hs rename to tests/integration/tests/6905-multi-test/files/myPackageC/src/LibC.hs diff --git a/tests/integration/tests/multi-test/files/myPackageC/test/Main.hs b/tests/integration/tests/6905-multi-test/files/myPackageC/test/Main.hs similarity index 100% rename from tests/integration/tests/multi-test/files/myPackageC/test/Main.hs rename to tests/integration/tests/6905-multi-test/files/myPackageC/test/Main.hs diff --git a/tests/integration/tests/multi-test/files/stack.yaml b/tests/integration/tests/6905-multi-test/files/stack.yaml similarity index 100% rename from tests/integration/tests/multi-test/files/stack.yaml rename to tests/integration/tests/6905-multi-test/files/stack.yaml