Skip to content

rustdoc-json: Inconsistant Enum Representation #93667

Closed
@aDotInTheVoid

Description

@aDotInTheVoid

Currently we use 3 different ways to serialse enums to json:

  1. For some of the enums, we use Adjacently tagged

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
#[serde(tag = "kind", content = "inner")]
pub enum Type {
/// Structs, enums, and traits
ResolvedPath {
name: String,
id: Id,
args: Option<Box<GenericArgs>>,
param_names: Vec<GenericBound>,
},
/// Parameterized types
Generic(String),
/// Fixed-size numeric types (plus int/usize/float), char, arrays, slices, and tuples
Primitive(String),
/// `extern "ABI" fn`
FunctionPointer(Box<FunctionPointer>),
/// `(String, u32, Box<usize>)`
Tuple(Vec<Type>),
/// `[u32]`
Slice(Box<Type>),
/// [u32; 15]
Array {
#[serde(rename = "type")]
type_: Box<Type>,
len: String,
},
/// `impl TraitA + TraitB + ...`
ImplTrait(Vec<GenericBound>),
/// `_`
Infer,
/// `*mut u32`, `*u8`, etc.
RawPointer {
mutable: bool,
#[serde(rename = "type")]
type_: Box<Type>,
},
/// `&'a mut String`, `&str`, etc.
BorrowedRef {
lifetime: Option<String>,
mutable: bool,
#[serde(rename = "type")]
type_: Box<Type>,
},
/// `<Type as Trait>::Name` or associated types like `T::Item` where `T: Iterator`
QualifiedPath {
name: String,
self_type: Box<Type>,
#[serde(rename = "trait")]
trait_: Box<Type>,
},
}

Which ends up looking like

              "output": {
                "inner": {
                  "lifetime": "'a",
                  "mutable": false,
                  "type": {"inner": "i32", "kind": "primitive"}
                },
                "kind": "borrowed_ref"
              }
  1. For others we use serdes default which is Externally tagged

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct GenericParamDef {
pub name: String,
pub kind: GenericParamDefKind,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum GenericParamDefKind {
Lifetime { outlives: Vec<String> },
Type { bounds: Vec<GenericBound>, default: Option<Type> },
Const { ty: Type, default: Option<String> },
}

Which gives output that looks like

          "params": [
            {
              "kind": {"lifetime": {"outlives": []}},
              "name": "'a"
            },
            {
              "kind": {"type": {"bounds": [], "default": null}},
              "name": "T"
            }
  1. Finaly we have the Item / ItemEnum, which are their own special weird, because of Remove Item::kind, use tagged enum. Rename variants to match #82613.
    Its basicly Ajacenctly tagged, but the tag/content are inlined to the Item

I'm not sure how much it matters which one we pick as almost all users will be going through the rust types, but it would be good to be consistant. I have no prefernce between 1 and 2, but 3 seems weird, so I dont think we should do that.

cc @CraftSpider

@rustbot modify labels: +C-discussion +A-rustdoc-json +T-rustdoc
but I think 3 is bad

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-rustdoc-jsonArea: Rustdoc JSON backendC-discussionCategory: Discussion or questions that doesn't represent real issues.T-rustdocRelevant to the rustdoc team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions