@@ -96,6 +96,9 @@ def decorator(func):
9696 ),
9797]
9898
99+ # Sphinx roles that are explicit references elsewhere and should always be links.
100+ ALWAYS_REF = {"doc" , "download" , "numref" , "ref" }
101+
99102
100103@check ("self" )
101104def check_self_links (work : LintWork ) -> Iterable [LintIssue ]:
@@ -135,6 +138,11 @@ def __init__(self, doctree: nodes.document) -> None:
135138 def visit_pending_xref (self , node : addnodes .pending_xref ) -> None :
136139 line = node_line_number (node )
137140 reftype = node .get ("reftype" )
141+ if reftype in ALWAYS_REF :
142+ # :ref: references are explicitly meant to be links, so should
143+ # never be unlinked. I don't know why someone would put a :ref:
144+ # to its own section, but who are we to judge?
145+ return
138146 target = node .get ("reftarget" )
139147
140148 if reftype == "meth" and "." not in target :
@@ -199,6 +207,10 @@ def find_duplicate_refs(doctree: nodes.document) -> Iterable[nodes.Node]:
199207 refs_by_target = defaultdict (list )
200208 for ref in para .findall (addnodes .pending_xref ):
201209 reftype = ref .get ("reftype" )
210+ if reftype in ALWAYS_REF :
211+ # :ref: references are explicitly meant to be links, so should
212+ # never be unlinked.
213+ continue
202214 target = ref .get ("reftarget" )
203215 assert reftype and target , (
204216 f"Reference missing reftype or target: { ref } \n { node_traceback (ref )} "
0 commit comments