Fix #12212: docs lost for re-exports across internal sub-libraries - #12226
Fix #12212: docs lost for re-exports across internal sub-libraries#12226nikita-volkov wants to merge 6 commits into
Conversation
13fdeaa to
cfd08df
Compare
Reproduces the issue where documentation is silently dropped for
identifiers re-exported through more than one hop across internal
sub-libraries when running 'cabal haddock --haddock-for-hackage'.
The root cause is that the internal sub-library's .haddock interface
file is generated under the ForHackage directory naming
('<pkg>-<version>-docs'), but the inplace package registration records
the path using ForDevelopment naming (just '<pkg>'), so the interface
file cannot be found when the main library's haddocks are built.
…ries When 'cabal haddock --haddock-for-hackage' was run on a package with internal sub-libraries, documentation for identifiers re-exported through those sub-libraries was silently dropped, with a 'Couldn't find .haddock for export' warning. Root cause: the internal sub-library's .haddock interface path was registered during 'build' using ForDevelopment directory naming (<pkgname>), but 'haddock --haddock-for-hackage' writes the interface to ForHackage naming (<pkgname>-<version>-docs). Since cabal invokes haddock separately per component, the main library's haddock phase still saw the stale build-step registration and could not locate the interface file. Fix: 1. inplaceInstalledPackageInfo now takes a HaddockTarget parameter so the haddock phase registers the correct directory naming. 2. haddockPackagePaths falls back to the alternate HaddockTarget directory naming when the registered .haddock path does not exist, handling stale in-memory indices from the build phase.
cfd08df to
0cdd50d
Compare
There was a problem hiding this comment.
Pull request overview
Fixes missing Haddock documentation for re-exports from internal sub-libraries by aligning interface paths across Haddock targets.
Changes:
- Makes in-place registration target-aware.
- Adds fallback interface-path discovery.
- Adds single-hop and multi-hop regression tests.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
changelog.d/12212.md |
Documents the fix. |
Cabal/src/Distribution/Simple/Register.hs |
Adds target-aware registration paths. |
Cabal/src/Distribution/Simple/Haddock.hs |
Adds alternate interface-path fallback. |
Cabal/src/Distribution/Simple/Build.hs |
Uses development paths during builds. |
cabal-testsuite/PackageTests/NewHaddock/HaddockReexportSingleHop/src/sub/Sub.hs |
Defines documented dependency. |
cabal-testsuite/PackageTests/NewHaddock/HaddockReexportSingleHop/src/lib/Mini.hs |
Re-exports dependency identifier. |
cabal-testsuite/PackageTests/NewHaddock/HaddockReexportSingleHop/single-hop-reexport.cabal |
Configures single-hop fixture. |
cabal-testsuite/PackageTests/NewHaddock/HaddockReexportSingleHop/cabal.test.hs |
Verifies retained documentation. |
cabal-testsuite/PackageTests/NewHaddock/HaddockReexportSingleHop/cabal.project |
Defines test project. |
cabal-testsuite/PackageTests/NewHaddock/HaddockReexportSingleHop/cabal.out |
Records expected output. |
cabal-testsuite/PackageTests/NewHaddock/HaddockReexportMultiHop/src/Public.hs |
Defines public re-export. |
cabal-testsuite/PackageTests/NewHaddock/HaddockReexportMultiHop/libs/internal/Internal/Leaf.hs |
Defines documented identifier. |
cabal-testsuite/PackageTests/NewHaddock/HaddockReexportMultiHop/libs/internal/Internal/Aggregate.hs |
Adds intermediate re-export. |
cabal-testsuite/PackageTests/NewHaddock/HaddockReexportMultiHop/haddock-reexport-multihop.cabal |
Configures multi-hop fixture. |
cabal-testsuite/PackageTests/NewHaddock/HaddockReexportMultiHop/cabal.test.hs |
Verifies multi-hop documentation. |
cabal-testsuite/PackageTests/NewHaddock/HaddockReexportMultiHop/cabal.project |
Defines test project. |
cabal-testsuite/PackageTests/NewHaddock/HaddockReexportMultiHop/cabal.out |
Records expected output. |
Suppressed comments (1)
Cabal/src/Distribution/Simple/Haddock.hs:1450
- This replaces every path component equal to the package name, not just the generated Haddock directory. In the common layout where package
foois checked out under a directory namedfoo, the fallback rewrites both the checkout root anddoc/html/foo, so it probes a nonexistent path and the original documentation-loss bug remains. Replace only the matching component nearest the interface file (or otherwise anchor the replacement to the Haddock output suffix).
replaceDir d
| d == devDir = hackageDir
| d == hackageDir = devDir
| otherwise = d
in joinPath (map replaceDir (splitDirectories path))
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…addock path The interface-path fallback rewrites every path component matching the package name, not just the haddock output directory. Haddock output always lives under doc/html/<dir>, so a package named 'html' has the name twice in its interface path and the fallback probes a path that does not exist.
The interface-path fallback swapped the HaddockTarget directory naming on every path component matching the package name, so any ancestor carrying the same name was rewritten too and the probed path did not exist. Rewrite only the component nearest the interface file.
Under --haddock-for-hackage the HTML half of --read-interface is the --html-location template that this mode always sets, so it stays correct when the interface half is rewritten to the ForHackage naming by the haddockPackagePaths fallback.
|
Fixes pushed. I don't know what the Whitespace failure is, seems like an unrelated issue, isn't it? |
The interface half of the '--read-interface' assertion checks a real filesystem path, so a hardcoded '/'-separated literal only matched on Unix. Build the expected fragment with System.FilePath instead.
Could you eloborate on this? We couldn't find the HaddockTarget when doing pair review in the cabal meeting. |
jappeace
left a comment
There was a problem hiding this comment.
Solid, thanks 🙏🏽
It scares me though how complicated it is to use haddock but that's a story for another day.
cabal haddock --haddock-for-hackagesilently dropped documentation for identifiers re-exported from internal sub-libraries, emitting a "Couldn't find .haddock for export" warning and showing 0% coverage for affected modules.Root cause: during
build, an internal sub-library's .haddock interface path is registered usingForDevelopmentdirectory naming (<pkgname>), buthaddock --haddock-for-hackagewrites the interface underForHackagenaming (<pkgname>-<version>-docs). Since cabal invokes haddock separately per component, the main library's haddock phase still saw the stale build-step registration and couldn't find the interface file.Fix:
inplaceInstalledPackageInfonow takes aHaddockTargetparameter so the haddock phase registers the correct directory naming.haddockPackagePathsfalls back to the alternateHaddockTargetdirectory naming when the registered.haddockpath doesn't exist, handling stale in-memory indices carried over from the build phase.Fixes #12212.
significance: significantin the changelog file.