diff --git a/cabal-install/src/Distribution/Client/ProjectBuilding/UnpackedPackage.hs b/cabal-install/src/Distribution/Client/ProjectBuilding/UnpackedPackage.hs index 7d9f34a8e8b..23dff3ff3ab 100644 --- a/cabal-install/src/Distribution/Client/ProjectBuilding/UnpackedPackage.hs +++ b/cabal-install/src/Distribution/Client/ProjectBuilding/UnpackedPackage.hs @@ -99,7 +99,7 @@ import qualified Data.ByteString.Lazy as LBS import qualified Data.ByteString.Lazy.Char8 as LBS.Char8 import qualified Data.List.NonEmpty as NE -import Control.Exception (ErrorCall, Handler (..), SomeAsyncException, assert, catches) +import Control.Exception (ErrorCall, Handler (..), SomeAsyncException, assert, catches, onException) import System.Directory (canonicalizePath, createDirectoryIfMissing, doesDirectoryExist, doesFileExist, removeFile) import System.FilePath (dropDrive, normalise, takeDirectory, (<.>), ()) import System.IO (Handle, IOMode (AppendMode), withFile) @@ -480,6 +480,10 @@ buildInplaceUnpackedPackage whenRebuild $ do timestamp <- beginUpdateFileMonitor runBuild + -- Be sure to invalidate the cache if building throws an exception! + -- If not, we'll abort execution with a stale recompilation cache. + -- See ghc#24926 for an example of how this can go wrong. + `onException` invalidatePackageRegFileMonitor packageFileMonitor let listSimple = execRebuild (getSymbolicPath srcdir) (needElaboratedConfiguredPackage pkg) diff --git a/cabal-testsuite/PackageTests/Recompilation/GHC24926/Repro.hs b/cabal-testsuite/PackageTests/Recompilation/GHC24926/Repro.hs new file mode 100644 index 00000000000..204872538ea --- /dev/null +++ b/cabal-testsuite/PackageTests/Recompilation/GHC24926/Repro.hs @@ -0,0 +1,6 @@ +import Process (a) +import Internal (Unused) + +main :: IO () +main = a + diff --git a/cabal-testsuite/PackageTests/Recompilation/GHC24926/cabal.test.hs b/cabal-testsuite/PackageTests/Recompilation/GHC24926/cabal.test.hs new file mode 100644 index 00000000000..607426f381c --- /dev/null +++ b/cabal-testsuite/PackageTests/Recompilation/GHC24926/cabal.test.hs @@ -0,0 +1,36 @@ +import Test.Cabal.Prelude + +-- See ghc#24926 +main = cabalTest $ do + recordMode DoNotRecord $ do + + root <- testTmpDir <$> getTestEnv + + writeInternalOrig root + cabal "test" [] + + liftIO $ writeFile (root ++ "/src/Internal.hs") + " module Internal where;\ + + \ data Unused = Unused;" + fails $ cabal "test" [] -- broken module on purpose + + writeInternalOrig root + out <- cabal' "test" [] -- shouldn't fail! + + assertOutputDoesNotContain + ": error:" out + assertOutputDoesNotContain + "Cannot continue after interface file error" out + + where + + writeInternalOrig r = liftIO $ do + writeFile (r ++ "/src/Internal.hs") + " module Internal where;\ + + \ data Unused = Unused;\ + + \ b :: IO (); \ + \ b = pure ();" + diff --git a/cabal-testsuite/PackageTests/Recompilation/GHC24926/repro.cabal b/cabal-testsuite/PackageTests/Recompilation/GHC24926/repro.cabal new file mode 100644 index 00000000000..30ad3d92d13 --- /dev/null +++ b/cabal-testsuite/PackageTests/Recompilation/GHC24926/repro.cabal @@ -0,0 +1,19 @@ +cabal-version: 3.0 +name: repro +version: 0.1.0.0 +build-type: Simple + +library + default-language: Haskell2010 + exposed-modules: + Internal + Process + build-depends: base + hs-source-dirs: src + +test-suite repro + default-language: Haskell2010 + type: exitcode-stdio-1.0 + main-is: Repro.hs + build-depends: base, repro + diff --git a/cabal-testsuite/PackageTests/Recompilation/GHC24926/src/Process.hs b/cabal-testsuite/PackageTests/Recompilation/GHC24926/src/Process.hs new file mode 100644 index 00000000000..919c5d46df5 --- /dev/null +++ b/cabal-testsuite/PackageTests/Recompilation/GHC24926/src/Process.hs @@ -0,0 +1,7 @@ +module Process where + +import Internal + +a :: IO () +a = b +