Should you use `-Wunused-packages` to keep cabal file tidy?

During some “routine” version bounds updates of some projects, I was informed that using ghc-options -Wunused-packages could help find out what dependencies are no longer valid. This helped a lot, so that those can be removed from cabal file, as opposed to scrambling around and get them compiled again.

The question is, it seems quite a good setting for keeping things tidy, but is it a good practice, and what are the downsides of using it?

7 Likes

…and should it by turned on -Wall (if it isn’t already)?

4 Likes

I really like it; only downside I observed so far is that is has false positives in certain scenarios: #24173: `-Wunused-packages` overreports with alternative Preludes · Issues · Glasgow Haskell Compiler / GHC · GitLab

1 Like

We found that cabal repl will sometimes give false positives for -Wunused-packages.

@EduardoLR10 worked with me on -Wunused-packages warnings finding ways to mitigate false positives reported when bringing up the REPL. Some examples are use of the .ghci configuration file, a cabal.project.local file and use of the command line to turn off the warning for the REPL only. The fact that cabal repl can report false positives is, I expect, a bug.

We found another bug where an empty ghc-options section in a common stanza masked the report of a unused package. Running cabal repl would unmask this so that subsequently it would be reported by cabal build (when it wasn’t before). Stack doesn’t report false positives on the warning except when stack repl is used without using target syntax. In that case stack presents a pick-a-target menu and in that case, I suspect, munges targets somehow to trigger a false positive warning. These problems are annoyances with the REPL but not with the build.

We also encountered false negatives, finding that stack is not always reporting -Werror=unused-packages. With a ghc-8.10.7 build cabal warns but stack doesn’t.

<no location info>: error: [-Wunused-packages, -Werror=unused-packages]
    The following packages were specified via -package or -package-id flags,
    but were not needed for compilation:
      - lens-4.19.2

Removing lens as a dependency, stack builds the package without complaint showing that the lens dependency was in fact unused.

One thing I take from this, and it is not the only example, is that stack and cabal have their strengths and weaknesses.

2 Likes

I always appreciate the heads up when I can remove a dependency, so I tend to integrate it into the general flags I use.

Not sure if it was remediated already, but there was a situation where it would list unused packages after compilation encountered an error, but it would list those that weren’t yet encountered yet, so it would say packageA is unused, even though it is used in modules that weren’t compiled because the compilation stopped prematurely (e.g. because of errors).

If you have a minimal reproducible example of GHC’s -Wunsed-packages not working as intended with Stack (false negatives), I would be grateful if you could post it at Stack’s repository - Stack #5569 would be a suitable issue. Then the Stack project can look into it.

If you use common stanzas, it will still report targets will report unused dependencies, even if at least one target within the package is using that dependency. Dependencies are tracked per-target, not per-package, which is more correct but a little different from other package managers.

For that, I prefer the existing behaviour which seems to be more “strict”, which is what I want. Not I guess you prefer it less strict.

1 Like

For public packages on Hackage, I agree that the status quo is superior. It’s been useful on internal packages to not have to write quite so much boilerplate, and because it’s internal it doesn’t push the consequences (in redundant dependencies) onto external consumers.

Yes, all components using a common build-depends need to be using those dependencies otherwise -Wunused-packages will trip. The warning message doesn’t say which component tripped the warning.

Those notes are from early 2023. Sorry, I don’t have a reproduction at hand but will be on the lookout, if it pops up again. I think we were on ghc-8.10.7 or ghc-9.2.4 at the time.

1 Like

Also, there seems an edge case that produces false positive too:

    build-depends: system-cxx-std-lib

I wonder if this could be a Cabal feature rather than a tricky library that doesn’t expose any Haskell modules.