Skip to content

Commit c52a0f8

Browse files
committed
rustdoc: correctly resolve link disambiguators through ctors
1 parent 9ff5fc4 commit c52a0f8

File tree

3 files changed

+61
-3
lines changed

3 files changed

+61
-3
lines changed

src/librustdoc/clean/utils.rs

+17
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,7 @@ pub(crate) fn synthesize_auto_trait_and_blanket_impls(
503503
/// [`href()`]: crate::html::format::href
504504
pub(crate) fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId {
505505
use DefKind::*;
506+
use rustc_hir::def::CtorOf;
506507
debug!("register_res({res:?})");
507508

508509
let (kind, did) = match res {
@@ -526,6 +527,22 @@ pub(crate) fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId {
526527
did,
527528
) => (kind.into(), did),
528529

530+
// Tuple and unit-like structs and enums exist in both type and
531+
// value ns. The item that exists in value ns is the "constructor,"
532+
// a special function or const that returns the constructed value.
533+
//
534+
// It's possible to make an intra-doc link that points at the
535+
// constructor, but it's not actually documented separately from
536+
// the type itself.
537+
Res::Def(Ctor(ctor_of, _), did) => (
538+
match ctor_of {
539+
CtorOf::Struct => Struct,
540+
CtorOf::Variant => Variant,
541+
}
542+
.into(),
543+
cx.tcx.parent(did),
544+
),
545+
529546
_ => panic!("register_res: unexpected {res:?}"),
530547
};
531548
if did.is_local() {

src/librustdoc/passes/collect_intra_doc_links.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1313
use rustc_data_structures::intern::Interned;
1414
use rustc_errors::{Applicability, Diag, DiagMessage};
1515
use rustc_hir::def::Namespace::*;
16-
use rustc_hir::def::{DefKind, Namespace, PerNS};
16+
use rustc_hir::def::{CtorOf, DefKind, Namespace, PerNS};
1717
use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
1818
use rustc_hir::{Mutability, Safety};
1919
use rustc_middle::ty::{Ty, TyCtxt};
@@ -212,7 +212,7 @@ impl UrlFragment {
212212
}
213213
DefKind::AssocConst => "associatedconstant.",
214214
DefKind::AssocTy => "associatedtype.",
215-
DefKind::Variant => "variant.",
215+
DefKind::Variant | DefKind::Ctor(CtorOf::Variant, _) => "variant.",
216216
DefKind::Field => {
217217
let parent_id = tcx.parent(def_id);
218218
if tcx.def_kind(parent_id) == DefKind::Variant {
@@ -423,7 +423,11 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
423423
if let Some(res) = self.resolve_path(path_str, ns, item_id, module_id) {
424424
return Ok(match res {
425425
Res::Def(
426-
DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Variant,
426+
DefKind::AssocFn
427+
| DefKind::AssocConst
428+
| DefKind::AssocTy
429+
| DefKind::Variant
430+
| DefKind::Ctor(CtorOf::Variant, _),
427431
def_id,
428432
) => {
429433
vec![(Res::from_def_id(self.cx.tcx, self.cx.tcx.parent(def_id)), Some(def_id))]

tests/rustdoc/intra-doc/value-ctor.rs

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// https://github.com/rust-lang/rust/issues/130591
2+
#![deny(rustdoc::broken_intra_doc_links)]
3+
#![crate_name = "foo"]
4+
5+
/// [value@Foo::X]
6+
//@ has foo/enum.Foo.html '//a[@href="enum.Foo.html#variant.X"]' 'Foo::X'
7+
pub enum Foo {
8+
X,
9+
}
10+
11+
/// [tst][value@MyStruct]
12+
//@ has foo/struct.MyStruct.html '//a[@href="struct.MyStruct.html"]' 'tst'
13+
pub struct MyStruct;
14+
15+
pub enum MyEnum {
16+
Internals,
17+
}
18+
19+
pub use MyEnum::*;
20+
21+
/// In this context, [a][type@Internals] is a struct, while [b][value@Internals] is an enum variant.
22+
//@ has foo/struct.Internals.html '//a[@href="struct.Internals.html"]' 'a'
23+
//@ has foo/struct.Internals.html '//a[@href="enum.MyEnum.html#variant.Internals"]' 'b'
24+
pub struct Internals {
25+
foo: (),
26+
}
27+
28+
pub mod inside {
29+
pub struct Internals2;
30+
}
31+
32+
use inside::*;
33+
34+
/// In this context, [a][type@Internals2] is an enum, while [b][value@Internals2] is a struct.
35+
//@ has foo/enum.Internals2.html '//a[@href="enum.Internals2.html"]' 'a'
36+
//@ has foo/enum.Internals2.html '//a[@href="inside/struct.Internals2.html"]' 'b'
37+
pub enum Internals2 {}

0 commit comments

Comments
 (0)