Skip to content

Commit c8614a7

Browse files
authored
Rollup merge of rust-lang#107912 - clubby789:doc-bad-enum-field, r=camelid,GuillaumeGomez
rustdoc: Don't resolve link to field on different variant Fix rust-lang#107903 This also gives a more specific diagnostic when the enum has any fields
2 parents f95f68e + ef8de38 commit c8614a7

File tree

3 files changed

+54
-5
lines changed

3 files changed

+54
-5
lines changed

src/librustdoc/passes/collect_intra_doc_links.rs

+25-4
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
297297
match ty_res {
298298
Res::Def(DefKind::Enum, did) => match tcx.type_of(did).kind() {
299299
ty::Adt(def, _) if def.is_enum() => {
300-
if let Some(field) = def.all_fields().find(|f| f.name == variant_field_name) {
300+
if let Some(variant) = def.variants().iter().find(|v| v.name == variant_name)
301+
&& let Some(field) = variant.fields.iter().find(|f| f.name == variant_field_name) {
301302
Ok((ty_res, field.did))
302303
} else {
303304
Err(UnresolvedPath {
@@ -1716,15 +1717,35 @@ fn resolution_failure(
17161717

17171718
// Otherwise, it must be an associated item or variant
17181719
let res = partial_res.expect("None case was handled by `last_found_module`");
1719-
let kind = match res {
1720-
Res::Def(kind, _) => Some(kind),
1720+
let kind_did = match res {
1721+
Res::Def(kind, did) => Some((kind, did)),
17211722
Res::Primitive(_) => None,
17221723
};
1723-
let path_description = if let Some(kind) = kind {
1724+
let is_struct_variant = |did| {
1725+
if let ty::Adt(def, _) = tcx.type_of(did).kind()
1726+
&& def.is_enum()
1727+
&& let Some(variant) = def.variants().iter().find(|v| v.name == res.name(tcx)) {
1728+
// ctor is `None` if variant is a struct
1729+
variant.ctor.is_none()
1730+
} else {
1731+
false
1732+
}
1733+
};
1734+
let path_description = if let Some((kind, did)) = kind_did {
17241735
match kind {
17251736
Mod | ForeignMod => "inner item",
17261737
Struct => "field or associated item",
17271738
Enum | Union => "variant or associated item",
1739+
Variant if is_struct_variant(did) => {
1740+
let variant = res.name(tcx);
1741+
let note = format!("variant `{variant}` has no such field");
1742+
if let Some(span) = sp {
1743+
diag.span_label(span, &note);
1744+
} else {
1745+
diag.note(&note);
1746+
}
1747+
return;
1748+
}
17281749
Variant
17291750
| Field
17301751
| Closure

tests/rustdoc-ui/intra-doc/errors.rs

+16
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,19 @@ pub trait T {
103103
macro_rules! m {
104104
() => {};
105105
}
106+
107+
///[`TestEnum::Variant1::field_name`]
108+
//~^ ERROR unresolved link
109+
//~| NOTE variant `Variant1` has no such field
110+
pub enum TestEnum {
111+
Variant1 {},
112+
Variant2 { field_name: u64 },
113+
}
114+
115+
///[`TestEnumNoFields::Variant1::field_name`]
116+
//~^ ERROR unresolved link
117+
//~| NOTE `Variant1` is a variant, not a module or type, and cannot have associated items
118+
pub enum TestEnumNoFields {
119+
Variant1 (),
120+
Variant2 {},
121+
}

tests/rustdoc-ui/intra-doc/errors.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,18 @@ error: unresolved link to `T::h`
142142
LL | /// [T::h!]
143143
| ^^^^^ the trait `T` has no macro named `h`
144144

145+
error: unresolved link to `TestEnum::Variant1::field_name`
146+
--> $DIR/errors.rs:107:6
147+
|
148+
LL | ///[`TestEnum::Variant1::field_name`]
149+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ variant `Variant1` has no such field
150+
151+
error: unresolved link to `TestEnumNoFields::Variant1::field_name`
152+
--> $DIR/errors.rs:115:6
153+
|
154+
LL | ///[`TestEnumNoFields::Variant1::field_name`]
155+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Variant1` is a variant, not a module or type, and cannot have associated items
156+
145157
error: unresolved link to `m`
146158
--> $DIR/errors.rs:98:6
147159
|
@@ -153,5 +165,5 @@ help: to link to the macro, add an exclamation mark
153165
LL | /// [m!()]
154166
| +
155167

156-
error: aborting due to 20 previous errors
168+
error: aborting due to 22 previous errors
157169

0 commit comments

Comments
 (0)