diff --git a/doc/maintainers/stack_errors.md b/doc/maintainers/stack_errors.md index e24a902b13..3f6b93190f 100644 --- a/doc/maintainers/stack_errors.md +++ b/doc/maintainers/stack_errors.md @@ -5,7 +5,7 @@ In connection with considering Stack's support of the [Haskell Error Index](https://errors.haskell.org/) initiative, this page seeks to take stock of the errors that Stack itself can raise, by reference to the -`master` branch of the Stack repository. Last updated: 2025-08-16. +`master` branch of the Stack repository. Last updated: 2026-03-15. * `Stack.main`: catches exceptions from action `commandLineHandler`. @@ -78,10 +78,10 @@ to take stock of the errors that Stack itself can raise, by reference to the [S-8575] = SnapshotNotSupportedException (Maybe Project) (Maybe AbstractSnapshot) ~~~ - - `Stack.Config.Nix.ConfigNixException` + - `Stack.Config.Nix.ConfigNixPrettyException` ~~~haskell - [S-2726] = NixCannotUseShellFileAndPackagesException + [S-2726] = NixCannotUseShellFileAndPackagesException FilePath [Text] [S-9317] | GHCMajorVersionUnspecified [S-8605] | OnlyGHCSupported ~~~ @@ -208,7 +208,7 @@ to take stock of the errors that Stack itself can raise, by reference to the [S-3113] | AttemptedOverwrites [Path Abs File] ~~~ - - `Stack.Nix.NixException` + - `Stack.Nix.NixPrettyException` ~~~haskell [S-7384] = CannotDetermineProjectRoot diff --git a/src/Stack/Config/Nix.hs b/src/Stack/Config/Nix.hs index c80b866543..90a64d35f7 100644 --- a/src/Stack/Config/Nix.hs +++ b/src/Stack/Config/Nix.hs @@ -12,13 +12,13 @@ Nix configuration. -} module Stack.Config.Nix - ( ConfigNixException + ( ConfigNixPrettyException , nixCompiler , nixCompilerVersion , nixOptsFromMonoid ) where -import Control.Monad.Extra ( ifM ) +import Control.Monad.Extra ( ifM, whenJust ) import qualified Data.Text as T import qualified Data.Text.IO as TIO import Distribution.System ( OS (..) ) @@ -28,26 +28,47 @@ import Stack.Types.Runner ( HasRunner ) import Stack.Types.Nix ( NixOpts (..), NixOptsMonoid (..) ) import System.Directory ( doesFileExist ) --- | Type representing exceptions thrown by functions exported by the +-- | Type representing \'pretty\' exceptions thrown by functions exported by the -- "Stack.Config.Nix" module. -data ConfigNixException - = NixCannotUseShellFileAndPackagesException +data ConfigNixPrettyException + = NixCannotUseShellFileAndPackagesException !FilePath ![Text] -- ^ Nix can't be given packages and a shell file at the same time | GHCMajorVersionUnspecified | OnlyGHCSupported deriving Show -instance Exception ConfigNixException where - displayException NixCannotUseShellFileAndPackagesException = - "Error: [S-2726]\n" - ++ "You cannot have packages and a shell-file filled at the same time \ - \in your nix-shell configuration." - displayException GHCMajorVersionUnspecified = - "Error: [S-9317]\n" - ++ "GHC major version not specified." - displayException OnlyGHCSupported = - "Error: [S-8605]\n" - ++ "Only GHC is supported by 'stack --nix'." +instance Pretty ConfigNixPrettyException where + pretty (NixCannotUseShellFileAndPackagesException initFile packages) = + "[S-2726]" + <> line + <> flow "The configuration of Stack's Nix integration cannot specify both \ + \a Nix shell file and Nix packages. You have specified:" + <> blankLine + <> spacedBulletedList + [ fillSep + [ flow "Shell file:" + , style File (fromString initFile) <> ";" + , "and" + ] + , fillSep $ + flow "Nix packages:" + : mkNarrativeList (Just Shell) False prettyPackages + ] + where + prettyPackages :: [StyleDoc] + prettyPackages = map (fromString . T.unpack) packages + pretty GHCMajorVersionUnspecified = + "[S-9317]" + <> line + <> flow "Stack's Nix integration requires at least a major version of GHC \ + \to be specified. No major version is specified." + pretty OnlyGHCSupported = + "[S-8605]" + <> line + <> flow "Stack's Nix integration supports only GHC binary distributions as \ + \compiler." + +instance Exception ConfigNixPrettyException -- | Interprets NixOptsMonoid options. nixOptsFromMonoid :: @@ -79,8 +100,9 @@ nixOptsFromMonoid nixMonoid os = do pure False else pure nixEnable0 - when (not (null packages) && isJust initFile) $ - throwIO NixCannotUseShellFileAndPackagesException + unless (null packages) $ whenJust initFile $ \fp -> + prettyThrowIO $ NixCannotUseShellFileAndPackagesException fp packages + pure NixOpts { enable , pureShell @@ -93,7 +115,7 @@ nixOptsFromMonoid nixMonoid os = do prefixAll p (x:xs) = p : x : prefixAll p xs prefixAll _ _ = [] -nixCompiler :: WantedCompiler -> Either ConfigNixException T.Text +nixCompiler :: WantedCompiler -> Either ConfigNixPrettyException T.Text nixCompiler compilerVersion = case compilerVersion of WCGhc version -> @@ -119,7 +141,7 @@ nixCompiler compilerVersion = WCGhcjs{} -> Left OnlyGHCSupported WCGhcGit{} -> Left OnlyGHCSupported -nixCompilerVersion :: WantedCompiler -> Either ConfigNixException T.Text +nixCompilerVersion :: WantedCompiler -> Either ConfigNixPrettyException T.Text nixCompilerVersion compilerVersion = case compilerVersion of WCGhc version -> diff --git a/src/Stack/Nix.hs b/src/Stack/Nix.hs index 0387706ef5..666280052e 100644 --- a/src/Stack/Nix.hs +++ b/src/Stack/Nix.hs @@ -36,17 +36,20 @@ import Stack.Types.Version ( showStackVersion ) import System.Environment ( getArgs, lookupEnv ) import qualified System.FilePath as F --- | Type representing exceptions thrown by functions exported by the --- "Stack.Nix" module. -data NixException +-- | Type representing \'pretty\' exceptions thrown by functions exported by +-- the "Stack.Nix" module. +data NixPrettyException = CannotDetermineProjectRoot -- ^ Can't determine the project root (location of the shell file if any). deriving Show -instance Exception NixException where - displayException CannotDetermineProjectRoot = - "Error: [S-7384]\n" - ++ "Cannot determine project root directory." +instance Pretty NixPrettyException where + pretty CannotDetermineProjectRoot = + "[S-7384]" + <> line + <> flow "Cannot determine project root directory." + +instance Exception NixPrettyException -- | Execute @nix-shell@, replacing the current process. runShellAndExit :: RIO Config void @@ -77,8 +80,8 @@ runShellAndExit = do -- (thus the void return type) compilerVersion <- withBuildConfig $ view wantedCompilerVersionL - ghc <- either throwIO pure $ nixCompiler compilerVersion - ghcVersion <- either throwIO pure $ nixCompilerVersion compilerVersion + ghc <- either prettyThrowIO pure $ nixCompiler compilerVersion + ghcVersion <- either prettyThrowIO pure $ nixCompilerVersion compilerVersion let pkgsInConfig = config.nix.packages -- It appears that cacert needs to be specified in order for -- crypton-x509-system >= 1.6.8 to work with Stack's Nix integration: