ci: refuse relative markdown links in rust doc comments

check-doc-refs.sh's relative arm resolved every link against the linking
file's directory. That is right for markdown and wrong for a .rs doc
comment: rustdoc emits the href verbatim onto a page under
target/doc/<crate>/<module...>/, so the link resolves against THAT
directory instead.

The consequence was a false pass, not a miss -- a link resolving from the
source dir got certified while rendering broken in the published docs.
Reproduced against main's script: a `](../../docs/README.md)` planted in
hive-forge/src/client.rs resolves from hive-forge/src/ and the old rule
exits 0.

Refused rather than resolved rustdoc-aware. The repo has zero relative
links in .rs doc comments (measured on 54daf9ac), so nothing needs the
second reader, and the backticked repo-root form the root arm already
gates renders correctly under both. Inferring module nesting would be
machinery in service of a form nothing uses.

Closes #3928
This commit is contained in:
atlas 2026-09-02 11:42:04 +02:00 committed by mara
commit 8f56f86df5

View file

@ -60,6 +60,26 @@ while IFS=: read -r file lineno match; do
[ -n "${match:-}" ] || continue
exempt "$file" "$lineno" && continue
link="${match#](}"
# A `.rs` doc comment has a second renderer, and it does not count `../`
# the way the rest of this arm assumes. rustdoc emits the href verbatim
# onto a page at `target/doc/<crate>/<module…>/`, so the link resolves
# against *that* directory, not the source file's. Resolving from the
# source therefore certifies links that render broken — a false pass, not
# a miss, and worse than no check.
#
# Refused rather than resolved rustdoc-aware: the repo has zero relative
# links in `.rs` doc comments (measured on this commit), so nothing needs
# the second reader, and the backticked repo-root form the root arm above
# already gates works under both. Inferring module nesting would be
# machinery in service of a form nothing uses.
case "$file" in
*.rs)
dead=$((dead + 1))
printf '::error file=%s,line=%s::relative markdown link in a rust doc comment renders against the rustdoc output directory, not this file; use a backticked repo-root pointer instead: %s\n' \
"$file" "$lineno" "$link"
continue
;;
esac
# Resolved from the linking file's directory, so `../` counts the same way
# the renderer counts it. `-m` keeps a link that escapes the repo root
# resolvable enough to report rather than erroring out here.