Rollup merge of #107912 - clubby789:doc-bad-enum-field, r=camelid,GuillaumeGomez

rustdoc: Don't resolve link to field on different variant

Fix #107903

This also gives a more specific diagnostic when the enum has any fields
This commit is contained in:
Matthias Krüger 2023-02-11 17:18:45 +01:00 committed by GitHub
commit c8614a7479
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 54 additions and 5 deletions

View file

@ -297,7 +297,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
match ty_res {
Res::Def(DefKind::Enum, did) => match tcx.type_of(did).kind() {
ty::Adt(def, _) if def.is_enum() => {
if let Some(field) = def.all_fields().find(|f| f.name == variant_field_name) {
if let Some(variant) = def.variants().iter().find(|v| v.name == variant_name)
&& let Some(field) = variant.fields.iter().find(|f| f.name == variant_field_name) {
Ok((ty_res, field.did))
} else {
Err(UnresolvedPath {
@ -1716,15 +1717,35 @@ fn resolution_failure(
// Otherwise, it must be an associated item or variant
let res = partial_res.expect("None case was handled by `last_found_module`");
let kind = match res {
Res::Def(kind, _) => Some(kind),
let kind_did = match res {
Res::Def(kind, did) => Some((kind, did)),
Res::Primitive(_) => None,
};
let path_description = if let Some(kind) = kind {
let is_struct_variant = |did| {
if let ty::Adt(def, _) = tcx.type_of(did).kind()
&& def.is_enum()
&& let Some(variant) = def.variants().iter().find(|v| v.name == res.name(tcx)) {
// ctor is `None` if variant is a struct
variant.ctor.is_none()
} else {
false
}
};
let path_description = if let Some((kind, did)) = kind_did {
match kind {
Mod | ForeignMod => "inner item",
Struct => "field or associated item",
Enum | Union => "variant or associated item",
Variant if is_struct_variant(did) => {
let variant = res.name(tcx);
let note = format!("variant `{variant}` has no such field");
if let Some(span) = sp {
diag.span_label(span, &note);
} else {
diag.note(&note);
}
return;
}
Variant
| Field
| Closure

View file

@ -103,3 +103,19 @@ pub trait T {
macro_rules! m {
() => {};
}
///[`TestEnum::Variant1::field_name`]
//~^ ERROR unresolved link
//~| NOTE variant `Variant1` has no such field
pub enum TestEnum {
Variant1 {},
Variant2 { field_name: u64 },
}
///[`TestEnumNoFields::Variant1::field_name`]
//~^ ERROR unresolved link
//~| NOTE `Variant1` is a variant, not a module or type, and cannot have associated items
pub enum TestEnumNoFields {
Variant1 (),
Variant2 {},
}

View file

@ -142,6 +142,18 @@ error: unresolved link to `T::h`
LL | /// [T::h!]
| ^^^^^ the trait `T` has no macro named `h`
error: unresolved link to `TestEnum::Variant1::field_name`
--> $DIR/errors.rs:107:6
|
LL | ///[`TestEnum::Variant1::field_name`]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ variant `Variant1` has no such field
error: unresolved link to `TestEnumNoFields::Variant1::field_name`
--> $DIR/errors.rs:115:6
|
LL | ///[`TestEnumNoFields::Variant1::field_name`]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Variant1` is a variant, not a module or type, and cannot have associated items
error: unresolved link to `m`
--> $DIR/errors.rs:98:6
|
@ -153,5 +165,5 @@ help: to link to the macro, add an exclamation mark
LL | /// [m!()]
| +
error: aborting due to 20 previous errors
error: aborting due to 22 previous errors