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:
commit
c8614a7479
3 changed files with 54 additions and 5 deletions
|
@ -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, ¬e);
|
||||
} else {
|
||||
diag.note(¬e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Variant
|
||||
| Field
|
||||
| Closure
|
||||
|
|
|
@ -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 {},
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue