Skip to content

rustdoc extreme slowdown with cyclic generic structures #160105

Description

@fjarri

Consider this MRE:

#![no_std]

extern crate alloc;

use alloc::{
    collections::{BTreeMap, BTreeSet},
    string::String,
    sync::Arc,
};

pub trait Erasable: Sync {}

impl<T> Erasable for T where T: Sync {}

pub trait SessionParameters {
    type Verifier;
}

pub struct Node<T>(pub Arc<T>);

pub struct ComputeScalar<SP: SessionParameters> {
    pub args: BTreeMap<String, ComputeScalarArg<SP>>,
    pub dependencies: Dependency<SP>,
}

pub struct Collect<SP: SessionParameters> {
    pub values: CollectArg<SP>,
    pub dependencies: Dependency<SP>,
}

pub struct ComputeMapping<SP: SessionParameters> {
    pub args: BTreeMap<String, ComputeMappingArg<SP>>,
    pub dependencies: Dependency<SP>,
}

pub struct SerializeAndSignBC<SP: SessionParameters> {
    pub data: Node<ComputeScalar<SP>>,
    pub dependencies: Dependency<SP>,
}

pub struct SerializeAndSignDM<SP: SessionParameters> {
    pub data: DirectMessageArg<SP>,
    pub dependencies: Dependency<SP>,
}

pub struct DeserializeAndCheck<SP: SessionParameters> {
    pub data: Node<Receive<SP>>,
    pub dependencies: Dependency<SP>,
}

pub struct SendDM<SP: SessionParameters> {
    pub data: Node<SerializeAndSignDM<SP>>,
    pub dependencies: Dependency<SP>,
}

pub struct SendBC<SP: SessionParameters> {
    pub data: Node<SerializeAndSignBC<SP>>,
    pub destinations: BTreeSet<SP::Verifier>,
    pub dependencies: Dependency<SP>,
}

pub struct Receive<SP: SessionParameters> {
    pub dependencies: Dependency<SP>,
}

pub struct MergeScalars<SP: SessionParameters> {
    pub left: ComputeScalarArg<SP>,
    pub right: ComputeScalarArg<SP>,
}

pub enum ComputeScalarArg<SP: SessionParameters> {
    ComputeScalar(Node<ComputeScalar<SP>>),
    MergeScalars(Node<MergeScalars<SP>>),
    Collect(Node<Collect<SP>>),
}

pub enum ComputeMappingArg<SP: SessionParameters> {
    ComputeScalar(Node<ComputeScalar<SP>>),
    MergeScalars(Node<MergeScalars<SP>>),
    Collect(Node<Collect<SP>>),
    ComputeMapping(Node<ComputeMapping<SP>>),
    SerializeAndSignBC(Node<SerializeAndSignBC<SP>>),
    SerializeAndSignDM(Node<SerializeAndSignDM<SP>>),
    DeserializeAndCheck(Node<DeserializeAndCheck<SP>>),
}

pub enum CollectArg<SP: SessionParameters> {
    ComputeMapping(Node<ComputeMapping<SP>>),
    SerializeAndSign(Node<SerializeAndSignDM<SP>>),
    DeserializeAndCheck(Node<DeserializeAndCheck<SP>>),
    Send(Node<SendDM<SP>>),
    Receive(Node<Receive<SP>>),
}

pub enum DirectMessageArg<SP: SessionParameters> {
    ComputeScalar(Node<ComputeScalar<SP>>),
    ComputeMapping(Node<ComputeMapping<SP>>),
    DeserializeAndCheck(Node<DeserializeAndCheck<SP>>),
}

pub enum Dependency<SP: SessionParameters> {
    ComputeScalar(Node<ComputeScalar<SP>>),
    Collect(Node<Collect<SP>>),
    MergeScalars(Node<MergeScalars<SP>>),
    SendBC(Node<SendBC<SP>>),
}

After creating a new library crate for it, running cargo doc --no-deps takes ~2 minutes on my machine. Removing the blanket impl impl<T> Erasable for T where T: Sync {} reduces the time to 0.5 seconds.

The problem seems to be caused by a combination of:

  • a public trait with a blanket impl
  • the trait is bound on Sync
  • closed loops of connections of structures to their fields (e.g. ComputeScalar -> Dependency -> ComputeScalar)
  • structures being generic
  • the trait that's the bound for that generic type having an associated type, and that type being used in some structs
  • some fields being BTreeMap/BTreeSet of other structs

Removing any one of these either removes the problem completely, or reduces the documentation generation time dramatically (e.g. from 2 minutes to 10 seconds, which is still disproportionately much, of course).

Meta

rustc --version --verbose:

rustc 1.97.1 (8bab26f4f 2026-07-14)
binary: rustc
commit-hash: 8bab26f4f68e0e26f0bb7960be334d5b520ea452
commit-date: 2026-07-14
host: aarch64-apple-darwin
release: 1.97.1
LLVM version: 22.1.6

Also tried on nightly, with the same results:

rustc 1.99.0-nightly (dc3f85158 2026-07-26)
binary: rustc
commit-hash: dc3f85158a955a87a6e4363af1fbe9cf2d063cce
commit-date: 2026-07-26
host: aarch64-apple-darwin
release: 1.99.0-nightly
LLVM version: 22.1.8

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.T-rustdocRelevant to the rustdoc team, which will review and decide on the PR/issue.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions